]> git.lyx.org Git - lyx.git/blob - src/output_docbook.C
moving LatexParam functionality into .layout files
[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                                 InsetOld * inset = par->getInset(0);
153                                 InsetOld::Code lyx_code = inset->lyxCode();
154                                 if (lyx_code == InsetOld::LABEL_CODE) {
155                                         command_name += " id=\"";
156                                         command_name += (static_cast<InsetCommand *>(inset))->getContents();
157                                         command_name += '"';
158                                         labelid = true;
159                                 }
160                         }
161                         if (!labelid && !style->latexparam().empty()) {
162                                 ls = style->latexparam();
163                                 if (ls.find('#') != string::npos) {
164                                         string el = expandLabel(buf.params().getLyXTextClass(), 
165                                                 style, false);
166                                         ls = subst(ls, "#", el);
167                                 } 
168                         }
169                         
170                         sgml::openTag(os, depth + command_depth, false, command_name, ls);
171
172                         // Label around sectioning number:
173                         if (!style->labeltag().empty()) {
174                                 sgml::openTag(os, depth + 1 + command_depth, false, 
175                                         style->labeltag());
176                                 os << expandLabel(buf.params().getLyXTextClass(), style, false);
177                                 sgml::closeTag(os, depth + 1 + command_depth, false, 
178                                         style->labeltag());
179                         }
180
181                         // Inner tagged header text, e.g. <title> for sectioning:
182                         sgml::openTag(os, depth + 1 + command_depth, false, 
183                                 style->innertag());
184                         break;
185
186                 case LATEX_ENVIRONMENT:
187                 case LATEX_ITEM_ENVIRONMENT:
188                         if (depth < par->params().depth()) {
189                                 depth = par->params().depth();
190                                 environment_stack[depth].erase();
191                         }
192
193                         if (environment_stack[depth] != style->latexname()) {
194                                 if (environment_stack.size() == depth + 1) {
195                                         environment_stack.push_back("!-- --");
196                                         environment_inner.push_back("!-- --");
197                                 }
198                                 environment_stack[depth] = style->latexname();
199                                 environment_inner[depth] = "!-- --";
200                                 // outputs <environment_stack[depth] latexparam()>
201                                 sgml::openTag(os, depth + command_depth, false, 
202                                                 environment_stack[depth], style->latexparam());
203                         } else {
204                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
205                                         style->itemtag(), command_depth + depth);
206                         }
207
208                         if (style->latextype == LATEX_ENVIRONMENT) {
209                                 if (!style->innertag().empty()) {
210                                         if (style->innertag() == "CDATA")
211                                                 os << "<![CDATA[";
212                                         else
213                                                 sgml::openTag(os, depth + command_depth, false, 
214                                                         style->innertag());
215                                 }
216                                 break;
217                         }
218
219                         environment_inner[depth] = style->innertag();
220
221                         if (!environment_inner[depth].empty())
222                                 sgml::openTag(os, depth + 1 + command_depth,
223                                     false, environment_inner[depth]);
224                         break;
225                 default:
226                         sgml::openTag(os, depth + command_depth,
227                                     false, style->latexname());
228                         break;
229                 }
230
231                 par->simpleDocBookOnePar(buf, os, outerFont(par, paragraphs),
232                                          runparams, depth + 1 + command_depth, labelid);
233
234                 // write closing SGML tags
235                 switch (style->latextype) {
236                 case LATEX_COMMAND:
237                         sgml::closeTag(os, depth + command_depth, false, 
238                                 style->innertag());
239                         break;
240                 case LATEX_ENVIRONMENT:
241                         if (!style->innertag().empty()) {
242                                 if (style->innertag() == "CDATA")
243                                         os << "]]>";
244                                 else
245                                         sgml::closeTag(os, depth + command_depth, false, 
246                                                 style->innertag());
247                         }
248                         break;
249                 case LATEX_ITEM_ENVIRONMENT:
250                         item_tag = style->itemtag();
251                         break;
252                 case LATEX_PARAGRAPH:
253                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
254                         break;
255                 default:
256                         sgml::closeTag(os, depth + command_depth, false, style->latexname());
257                         break;
258                 }
259         }
260
261         // Close open tags
262         for (int d = depth; d >= 0; --d) {
263                 if (!environment_stack[depth].empty()) {
264                                 sgml::closeEnvTags(os, false, environment_inner[depth], 
265                                         item_tag, command_depth + depth);
266                 }
267         }
268
269         for (int j = command_depth; j >= 0 ; --j)
270                 if (!command_stack[j].empty()) {
271                         sgml::closeTag(os, j, false, command_stack[j]);
272                         os << endl;
273                 }
274 }
275