Root/
Source at commit 1322 created 12 years 7 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * $Id: $␊ |
4 | *␊ |
5 | *␊ |
6 | * Copyright (C) 1997-2011 by Dimitri van Heesch.␊ |
7 | *␊ |
8 | * Permission to use, copy, modify, and distribute this software and its␊ |
9 | * documentation under the terms of the GNU General Public License is hereby ␊ |
10 | * granted. No representations are made about the suitability of this software ␊ |
11 | * for any purpose. It is provided "as is" without express or implied warranty.␊ |
12 | * See the GNU General Public License for more details.␊ |
13 | *␊ |
14 | * Documents produced by Doxygen are derivative works derived from the␊ |
15 | * input used in their production; they are not affected by this license.␊ |
16 | *␊ |
17 | */␊ |
18 | ␊ |
19 | #include <qdir.h>␊ |
20 | #include "htmldocvisitor.h"␊ |
21 | #include "docparser.h"␊ |
22 | #include "language.h"␊ |
23 | #include "doxygen.h"␊ |
24 | #include "outputgen.h"␊ |
25 | #include "dot.h"␊ |
26 | #include "message.h"␊ |
27 | #include "config.h"␊ |
28 | #include "htmlgen.h"␊ |
29 | #include "parserintf.h"␊ |
30 | #include "msc.h"␊ |
31 | #include "util.h"␊ |
32 | ␊ |
33 | ␊ |
34 | static const int NUM_HTML_LIST_TYPES = 4;␊ |
35 | static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};␊ |
36 | ␊ |
37 | static QCString convertIndexWordToAnchor(const QString &word)␊ |
38 | {␊ |
39 | static char hex[] = "0123456789abcdef";␊ |
40 | uint i;␊ |
41 | QCString result;␊ |
42 | for (i=0;i<word.length();i++)␊ |
43 | {␊ |
44 | int c = word.at(i);␊ |
45 | if (isId(c))␊ |
46 | {␊ |
47 | result+=c;␊ |
48 | }␊ |
49 | else if (isspace(c))␊ |
50 | {␊ |
51 | result+="_";␊ |
52 | }␊ |
53 | else␊ |
54 | {␊ |
55 | char cs[3];␊ |
56 | cs[0]=hex[c>>4];␊ |
57 | cs[1]=hex[c&0xf];␊ |
58 | cs[2]=0;␊ |
59 | result+=cs;␊ |
60 | }␊ |
61 | }␊ |
62 | return result;␊ |
63 | }␊ |
64 | ␊ |
65 | static bool mustBeOutsideParagraph(DocNode *n)␊ |
66 | {␊ |
67 | switch (n->kind())␊ |
68 | {␊ |
69 | /* <ul> */␊ |
70 | case DocNode::Kind_HtmlList:␊ |
71 | case DocNode::Kind_SimpleList:␊ |
72 | case DocNode::Kind_AutoList:␊ |
73 | /* <dl> */␊ |
74 | case DocNode::Kind_SimpleSect:␊ |
75 | case DocNode::Kind_ParamSect:␊ |
76 | case DocNode::Kind_HtmlDescList:␊ |
77 | case DocNode::Kind_XRefItem:␊ |
78 | /* <table> */␊ |
79 | case DocNode::Kind_HtmlTable:␊ |
80 | /* <h?> */␊ |
81 | case DocNode::Kind_Section:␊ |
82 | case DocNode::Kind_HtmlHeader:␊ |
83 | /* \internal */␊ |
84 | case DocNode::Kind_Internal:␊ |
85 | /* <div> */␊ |
86 | case DocNode::Kind_Verbatim:␊ |
87 | case DocNode::Kind_Include:␊ |
88 | case DocNode::Kind_Image:␊ |
89 | case DocNode::Kind_SecRefList:␊ |
90 | /* <hr> */␊ |
91 | case DocNode::Kind_HorRuler:␊ |
92 | /* CopyDoc gets paragraph markers from the wrapping DocPara node,␊ |
93 | * but needs to insert them for all documentation being copied to␊ |
94 | * preserve formatting.␊ |
95 | */␊ |
96 | case DocNode::Kind_Copy:␊ |
97 | return TRUE;␊ |
98 | case DocNode::Kind_StyleChange:␊ |
99 | return ((DocStyleChange*)n)->style()==DocStyleChange::Preformatted ||␊ |
100 | ((DocStyleChange*)n)->style()==DocStyleChange::Div ||␊ |
101 | ((DocStyleChange*)n)->style()==DocStyleChange::Center;␊ |
102 | case DocNode::Kind_Formula:␊ |
103 | return !((DocFormula*)n)->isInline();␊ |
104 | default:␊ |
105 | break;␊ |
106 | }␊ |
107 | return FALSE;␊ |
108 | }␊ |
109 | ␊ |
110 | ␊ |
111 | ␊ |
112 | static QString htmlAttribsToString(const HtmlAttribList &attribs)␊ |
113 | {␊ |
114 | QString result;␊ |
115 | HtmlAttribListIterator li(attribs);␊ |
116 | HtmlAttrib *att;␊ |
117 | for (li.toFirst();(att=li.current());++li)␊ |
118 | {␊ |
119 | if (!att->value.isEmpty()) // ignore attribute without values as they␊ |
120 | // are not XHTML compliant␊ |
121 | {␊ |
122 | result+=" ";␊ |
123 | result+=att->name;␊ |
124 | result+="=\""+convertToXML(att->value)+"\"";␊ |
125 | }␊ |
126 | }␊ |
127 | return result;␊ |
128 | }␊ |
129 | ␊ |
130 | //-------------------------------------------------------------------------␊ |
131 | ␊ |
132 | HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,␊ |
133 | const char *langExt) ␊ |
134 | : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), ␊ |
135 | m_hide(FALSE), m_langExt(langExt)␊ |
136 | {␊ |
137 | }␊ |
138 | ␊ |
139 | //--------------------------------------␊ |
140 | // visitor functions for leaf nodes␊ |
141 | //--------------------------------------␊ |
142 | ␊ |
143 | void HtmlDocVisitor::visit(DocWord *w)␊ |
144 | {␊ |
145 | //printf("word: %s\n",w->word().data());␊ |
146 | if (m_hide) return;␊ |
147 | filter(w->word());␊ |
148 | }␊ |
149 | ␊ |
150 | void HtmlDocVisitor::visit(DocLinkedWord *w)␊ |
151 | {␊ |
152 | if (m_hide) return;␊ |
153 | startLink(w->ref(),w->file(),w->relPath(),w->anchor(),w->tooltip());␊ |
154 | filter(w->word());␊ |
155 | endLink();␊ |
156 | }␊ |
157 | ␊ |
158 | void HtmlDocVisitor::visit(DocWhiteSpace *w)␊ |
159 | {␊ |
160 | if (m_hide) return;␊ |
161 | if (m_insidePre)␊ |
162 | {␊ |
163 | m_t << w->chars();␊ |
164 | }␊ |
165 | else␊ |
166 | {␊ |
167 | m_t << " ";␊ |
168 | }␊ |
169 | }␊ |
170 | ␊ |
171 | void HtmlDocVisitor::visit(DocSymbol *s)␊ |
172 | {␊ |
173 | if (m_hide) return;␊ |
174 | switch(s->symbol())␊ |
175 | {␊ |
176 | case DocSymbol::BSlash: m_t << "\\"; break;␊ |
177 | case DocSymbol::At: m_t << "@"; break;␊ |
178 | case DocSymbol::Less: m_t << "<"; break;␊ |
179 | case DocSymbol::Greater: m_t << ">"; break;␊ |
180 | case DocSymbol::Amp: m_t << "&"; break;␊ |
181 | case DocSymbol::Dollar: m_t << "$"; break;␊ |
182 | case DocSymbol::Hash: m_t << "#"; break;␊ |
183 | case DocSymbol::DoubleColon: m_t << "::"; break;␊ |
184 | case DocSymbol::Percent: m_t << "%"; break;␊ |
185 | case DocSymbol::Copy: m_t << "©"; break;␊ |
186 | case DocSymbol::Tm: m_t << "™"; break;␊ |
187 | case DocSymbol::Reg: m_t << "®"; break;␊ |
188 | case DocSymbol::Apos: m_t << "'"; break;␊ |
189 | case DocSymbol::Quot: m_t << "\""; break;␊ |
190 | case DocSymbol::Lsquo: m_t << "‘"; break;␊ |
191 | case DocSymbol::Rsquo: m_t << "’"; break;␊ |
192 | case DocSymbol::Ldquo: m_t << "“"; break;␊ |
193 | case DocSymbol::Rdquo: m_t << "”"; break;␊ |
194 | case DocSymbol::Ndash: m_t << "–"; break;␊ |
195 | case DocSymbol::Mdash: m_t << "—"; break;␊ |
196 | case DocSymbol::Uml: m_t << "&" << s->letter() << "uml;"; break;␊ |
197 | case DocSymbol::Acute: m_t << "&" << s->letter() << "acute;"; break;␊ |
198 | case DocSymbol::Grave: m_t << "&" << s->letter() << "grave;"; break;␊ |
199 | case DocSymbol::Circ: m_t << "&" << s->letter() << "circ;"; break;␊ |
200 | case DocSymbol::Slash: m_t << "&" << s->letter() << "slash;"; break;␊ |
201 | case DocSymbol::Tilde: m_t << "&" << s->letter() << "tilde;"; break;␊ |
202 | case DocSymbol::Szlig: m_t << "ß"; break;␊ |
203 | case DocSymbol::Cedil: m_t << "&" << s->letter() << "cedil;"; break;␊ |
204 | case DocSymbol::Ring: m_t << "&" << s->letter() << "ring;"; break;␊ |
205 | case DocSymbol::Nbsp: m_t << " "; break;␊ |
206 | case DocSymbol::AElig: m_t << "Æ"; break;␊ |
207 | case DocSymbol::Aelig: m_t << "æ"; break;␊ |
208 | default:␊ |
209 | err("error: unknown symbol found\n");␊ |
210 | }␊ |
211 | }␊ |
212 | ␊ |
213 | void HtmlDocVisitor::visit(DocURL *u)␊ |
214 | {␊ |
215 | if (m_hide) return;␊ |
216 | m_t << "<a href=\"";␊ |
217 | if (u->isEmail()) m_t << "mailto:";␊ |
218 | m_t << u->url() << "\">";␊ |
219 | filter(u->url());␊ |
220 | m_t << "</a>";␊ |
221 | }␊ |
222 | ␊ |
223 | void HtmlDocVisitor::visit(DocLineBreak *)␊ |
224 | {␊ |
225 | if (m_hide) return;␊ |
226 | m_t << "<br/>\n";␊ |
227 | }␊ |
228 | ␊ |
229 | void HtmlDocVisitor::visit(DocHorRuler *)␊ |
230 | {␊ |
231 | if (m_hide) return;␊ |
232 | m_t << "<hr/>\n";␊ |
233 | }␊ |
234 | ␊ |
235 | void HtmlDocVisitor::visit(DocStyleChange *s)␊ |
236 | {␊ |
237 | if (m_hide) return;␊ |
238 | switch (s->style())␊ |
239 | {␊ |
240 | case DocStyleChange::Bold:␊ |
241 | if (s->enable()) m_t << "<b" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</b>";␊ |
242 | break;␊ |
243 | case DocStyleChange::Italic:␊ |
244 | if (s->enable()) m_t << "<em" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</em>";␊ |
245 | break;␊ |
246 | case DocStyleChange::Code:␊ |
247 | if (s->enable()) m_t << "<code" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</code>";␊ |
248 | break;␊ |
249 | case DocStyleChange::Subscript:␊ |
250 | if (s->enable()) m_t << "<sub" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sub>";␊ |
251 | break;␊ |
252 | case DocStyleChange::Superscript:␊ |
253 | if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sup>";␊ |
254 | break;␊ |
255 | case DocStyleChange::Center:␊ |
256 | if (s->enable()) ␊ |
257 | {␊ |
258 | forceEndParagraph(s);␊ |
259 | m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; ␊ |
260 | }␊ |
261 | else ␊ |
262 | {␊ |
263 | m_t << "</center>";␊ |
264 | forceStartParagraph(s);␊ |
265 | }␊ |
266 | break;␊ |
267 | case DocStyleChange::Small:␊ |
268 | if (s->enable()) m_t << "<small" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</small>";␊ |
269 | break;␊ |
270 | case DocStyleChange::Preformatted:␊ |
271 | if (s->enable())␊ |
272 | {␊ |
273 | forceEndParagraph(s);␊ |
274 | m_t << "<pre" << htmlAttribsToString(s->attribs()) << ">";␊ |
275 | m_insidePre=TRUE;␊ |
276 | }␊ |
277 | else␊ |
278 | {␊ |
279 | m_insidePre=FALSE;␊ |
280 | m_t << "</pre>";␊ |
281 | forceStartParagraph(s);␊ |
282 | }␊ |
283 | break;␊ |
284 | case DocStyleChange::Div:␊ |
285 | if (s->enable()) ␊ |
286 | {␊ |
287 | forceEndParagraph(s);␊ |
288 | m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; ␊ |
289 | }␊ |
290 | else ␊ |
291 | {␊ |
292 | m_t << "</div>";␊ |
293 | forceStartParagraph(s);␊ |
294 | }␊ |
295 | break;␊ |
296 | case DocStyleChange::Span:␊ |
297 | if (s->enable()) m_t << "<span" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</span>";␊ |
298 | break;␊ |
299 | ␊ |
300 | }␊ |
301 | }␊ |
302 | ␊ |
303 | ␊ |
304 | void HtmlDocVisitor::visit(DocVerbatim *s)␊ |
305 | {␊ |
306 | if (m_hide) return;␊ |
307 | switch(s->type())␊ |
308 | {␊ |
309 | case DocVerbatim::Code: ␊ |
310 | forceEndParagraph(s);␊ |
311 | m_t << PREFRAG_START;␊ |
312 | Doxygen::parserManager->getParser(m_langExt)␊ |
313 | ->parseCode(m_ci,s->context(),s->text(),␊ |
314 | s->isExample(),s->exampleFile());␊ |
315 | m_t << PREFRAG_END;␊ |
316 | forceStartParagraph(s);␊ |
317 | break;␊ |
318 | case DocVerbatim::Verbatim: ␊ |
319 | forceEndParagraph(s);␊ |
320 | m_t << PREFRAG_START;␊ |
321 | filter(s->text());␊ |
322 | m_t << PREFRAG_END;␊ |
323 | forceStartParagraph(s);␊ |
324 | break;␊ |
325 | case DocVerbatim::HtmlOnly: ␊ |
326 | m_t << s->text(); ␊ |
327 | break;␊ |
328 | case DocVerbatim::ManOnly: ␊ |
329 | case DocVerbatim::LatexOnly: ␊ |
330 | case DocVerbatim::XmlOnly: ␊ |
331 | /* nothing */ ␊ |
332 | break;␊ |
333 | ␊ |
334 | case DocVerbatim::Dot:␊ |
335 | {␊ |
336 | static int dotindex = 1;␊ |
337 | QCString fileName(4096);␊ |
338 | ␊ |
339 | fileName.sprintf("%s%d%s", ␊ |
340 | (Config_getString("HTML_OUTPUT")+"/inline_dotgraph_").data(), ␊ |
341 | dotindex++,␊ |
342 | ".dot"␊ |
343 | );␊ |
344 | QFile file(fileName);␊ |
345 | if (!file.open(IO_WriteOnly))␊ |
346 | {␊ |
347 | err("Could not open file %s for writing\n",fileName.data());␊ |
348 | }␊ |
349 | file.writeBlock( s->text(), s->text().length() );␊ |
350 | file.close();␊ |
351 | ␊ |
352 | forceEndParagraph(s);␊ |
353 | m_t << "<div align=\"center\">" << endl;␊ |
354 | writeDotFile(fileName,s->relPath(),s->context());␊ |
355 | m_t << "</div>" << endl;␊ |
356 | forceStartParagraph(s);␊ |
357 | ␊ |
358 | if (Config_getBool("DOT_CLEANUP")) file.remove();␊ |
359 | }␊ |
360 | break;␊ |
361 | case DocVerbatim::Msc:␊ |
362 | {␊ |
363 | static int mscindex = 1;␊ |
364 | QCString baseName(4096);␊ |
365 | ␊ |
366 | baseName.sprintf("%s%d", ␊ |
367 | (Config_getString("HTML_OUTPUT")+"/inline_mscgraph_").data(), ␊ |
368 | mscindex++␊ |
369 | );␊ |
370 | QFile file(baseName+".msc");␊ |
371 | if (!file.open(IO_WriteOnly))␊ |
372 | {␊ |
373 | err("Could not open file %s.msc for writing\n",baseName.data());␊ |
374 | }␊ |
375 | QCString text = "msc {";␊ |
376 | text+=s->text();␊ |
377 | text+="}";␊ |
378 | file.writeBlock( text, text.length() );␊ |
379 | file.close();␊ |
380 | ␊ |
381 | forceEndParagraph(s);␊ |
382 | m_t << "<div align=\"center\">" << endl;␊ |
383 | writeMscFile(baseName+".msc",s->relPath(),s->context());␊ |
384 | m_t << "</div>" << endl;␊ |
385 | forceStartParagraph(s);␊ |
386 | ␊ |
387 | if (Config_getBool("DOT_CLEANUP")) file.remove();␊ |
388 | }␊ |
389 | break;␊ |
390 | }␊ |
391 | }␊ |
392 | ␊ |
393 | void HtmlDocVisitor::visit(DocAnchor *anc)␊ |
394 | {␊ |
395 | if (m_hide) return;␊ |
396 | m_t << "<a class=\"anchor\" id=\"" << anc->anchor() << "\"></a>";␊ |
397 | }␊ |
398 | ␊ |
399 | void HtmlDocVisitor::visit(DocInclude *inc)␊ |
400 | {␊ |
401 | if (m_hide) return;␊ |
402 | switch(inc->type())␊ |
403 | {␊ |
404 | case DocInclude::Include: ␊ |
405 | forceEndParagraph(inc);␊ |
406 | m_t << PREFRAG_START;␊ |
407 | Doxygen::parserManager->getParser(inc->extension())␊ |
408 | ->parseCode(m_ci, ␊ |
409 | inc->context(),␊ |
410 | inc->text(),␊ |
411 | inc->isExample(),␊ |
412 | inc->exampleFile(),␊ |
413 | 0, // fd␊ |
414 | -1, // startLine␊ |
415 | -1, // endLine␊ |
416 | TRUE // inlineFragment␊ |
417 | );␊ |
418 | m_t << PREFRAG_END;␊ |
419 | forceStartParagraph(inc);␊ |
420 | break;␊ |
421 | case DocInclude::IncWithLines:␊ |
422 | { ␊ |
423 | forceEndParagraph(inc);␊ |
424 | m_t << PREFRAG_START;␊ |
425 | QFileInfo cfi( inc->file() );␊ |
426 | FileDef fd( cfi.dirPath(), cfi.fileName() );␊ |
427 | Doxygen::parserManager->getParser(inc->extension())␊ |
428 | ->parseCode(m_ci,␊ |
429 | inc->context(),␊ |
430 | inc->text(),␊ |
431 | inc->isExample(),␊ |
432 | inc->exampleFile(), &fd);␊ |
433 | m_t << PREFRAG_END;␊ |
434 | forceStartParagraph(inc);␊ |
435 | }␊ |
436 | break;␊ |
437 | case DocInclude::DontInclude: ␊ |
438 | break;␊ |
439 | case DocInclude::HtmlInclude: ␊ |
440 | m_t << inc->text(); ␊ |
441 | break;␊ |
442 | case DocInclude::VerbInclude: ␊ |
443 | forceEndParagraph(inc);␊ |
444 | m_t << PREFRAG_START;␊ |
445 | filter(inc->text());␊ |
446 | m_t << PREFRAG_END;␊ |
447 | forceStartParagraph(inc);␊ |
448 | break;␊ |
449 | }␊ |
450 | }␊ |
451 | ␊ |
452 | void HtmlDocVisitor::visit(DocIncOperator *op)␊ |
453 | {␊ |
454 | //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",␊ |
455 | // op->type(),op->isFirst(),op->isLast(),op->text().data());␊ |
456 | if (op->isFirst()) ␊ |
457 | {␊ |
458 | if (!m_hide) m_t << PREFRAG_START;␊ |
459 | pushEnabled();␊ |
460 | m_hide=TRUE;␊ |
461 | }␊ |
462 | if (op->type()!=DocIncOperator::Skip) ␊ |
463 | {␊ |
464 | popEnabled();␊ |
465 | if (!m_hide) ␊ |
466 | {␊ |
467 | Doxygen::parserManager->getParser(m_langExt)␊ |
468 | ->parseCode(m_ci,op->context(),␊ |
469 | op->text(),op->isExample(),␊ |
470 | op->exampleFile());␊ |
471 | }␊ |
472 | pushEnabled();␊ |
473 | m_hide=TRUE;␊ |
474 | }␊ |
475 | if (op->isLast()) ␊ |
476 | {␊ |
477 | popEnabled();␊ |
478 | if (!m_hide) m_t << PREFRAG_END;␊ |
479 | }␊ |
480 | else␊ |
481 | {␊ |
482 | if (!m_hide) m_t << endl;␊ |
483 | }␊ |
484 | }␊ |
485 | ␊ |
486 | void HtmlDocVisitor::visit(DocFormula *f)␊ |
487 | {␊ |
488 | if (m_hide) return;␊ |
489 | bool bDisplay = !f->isInline();␊ |
490 | if (bDisplay) ␊ |
491 | {␊ |
492 | forceEndParagraph(f);␊ |
493 | m_t << "<p class=\"formulaDsp\">" << endl;␊ |
494 | }␊ |
495 | ␊ |
496 | if (Config_getBool("USE_MATHJAX"))␊ |
497 | {␊ |
498 | QCString text = f->text();␊ |
499 | bool closeInline = FALSE;␊ |
500 | if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && ␊ |
501 | text.at(text.length()-1)=='$')␊ |
502 | {␊ |
503 | closeInline=TRUE;␊ |
504 | text = text.mid(1,text.length()-2);␊ |
505 | m_t << "\\(";␊ |
506 | }␊ |
507 | m_t << convertToHtml(text);␊ |
508 | if (closeInline)␊ |
509 | {␊ |
510 | m_t << "\\)";␊ |
511 | }␊ |
512 | }␊ |
513 | else␊ |
514 | {␊ |
515 | m_t << "<img class=\"formula" ␊ |
516 | << (bDisplay ? "Dsp" : "Inl");␊ |
517 | m_t << "\" alt=\"";␊ |
518 | filterQuotedCdataAttr(f->text());␊ |
519 | m_t << "\"";␊ |
520 | /// @todo cache image dimensions on formula generation and give height/width␊ |
521 | /// for faster preloading and better rendering of the page␊ |
522 | m_t << " src=\"" << f->relPath() << f->name() << ".png\"/>";␊ |
523 | ␊ |
524 | }␊ |
525 | if (bDisplay)␊ |
526 | {␊ |
527 | m_t << endl << "</p>" << endl;␊ |
528 | forceStartParagraph(f);␊ |
529 | }␊ |
530 | }␊ |
531 | ␊ |
532 | void HtmlDocVisitor::visit(DocIndexEntry *e)␊ |
533 | {␊ |
534 | QCString anchor = convertIndexWordToAnchor(e->entry());␊ |
535 | if (e->member()) ␊ |
536 | {␊ |
537 | anchor.prepend(e->member()->anchor()+"_");␊ |
538 | }␊ |
539 | m_t << "<a name=\"" << anchor << "\"></a>";␊ |
540 | //printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",␊ |
541 | // e->entry().data(),␊ |
542 | // e->scope() ? e->scope()->name().data() : "<null>",␊ |
543 | // e->member() ? e->member()->name().data() : "<null>"␊ |
544 | // );␊ |
545 | Doxygen::indexList.addIndexItem(e->scope(),e->member(),e->entry());␊ |
546 | }␊ |
547 | ␊ |
548 | void HtmlDocVisitor::visit(DocSimpleSectSep *)␊ |
549 | {␊ |
550 | m_t << "</dd>" << endl;␊ |
551 | m_t << "<dd>" << endl;␊ |
552 | }␊ |
553 | ␊ |
554 | //--------------------------------------␊ |
555 | // visitor functions for compound nodes␊ |
556 | //--------------------------------------␊ |
557 | ␊ |
558 | ␊ |
559 | void HtmlDocVisitor::visitPre(DocAutoList *l)␊ |
560 | {␊ |
561 | //printf("DocAutoList::visitPre\n");␊ |
562 | if (m_hide) return;␊ |
563 | forceEndParagraph(l);␊ |
564 | if (l->isEnumList())␊ |
565 | {␊ |
566 | //␊ |
567 | // Do list type based on depth:␊ |
568 | // 1.␊ |
569 | // a.␊ |
570 | // i.␊ |
571 | // A. ␊ |
572 | // 1. (repeat)...␊ |
573 | //␊ |
574 | m_t << "<ol type=\"" << types[l->depth() % NUM_HTML_LIST_TYPES] << "\">";␊ |
575 | }␊ |
576 | else␊ |
577 | {␊ |
578 | m_t << "<ul>";␊ |
579 | }␊ |
580 | if (!l->isPreformatted()) m_t << "\n";␊ |
581 | }␊ |
582 | ␊ |
583 | void HtmlDocVisitor::visitPost(DocAutoList *l)␊ |
584 | {␊ |
585 | //printf("DocAutoList::visitPost\n");␊ |
586 | if (m_hide) return;␊ |
587 | if (l->isEnumList())␊ |
588 | {␊ |
589 | m_t << "</ol>";␊ |
590 | }␊ |
591 | else␊ |
592 | {␊ |
593 | m_t << "</ul>";␊ |
594 | }␊ |
595 | if (!l->isPreformatted()) m_t << "\n";␊ |
596 | forceStartParagraph(l);␊ |
597 | }␊ |
598 | ␊ |
599 | void HtmlDocVisitor::visitPre(DocAutoListItem *)␊ |
600 | {␊ |
601 | if (m_hide) return;␊ |
602 | m_t << "<li>";␊ |
603 | }␊ |
604 | ␊ |
605 | void HtmlDocVisitor::visitPost(DocAutoListItem *li) ␊ |
606 | {␊ |
607 | if (m_hide) return;␊ |
608 | m_t << "</li>";␊ |
609 | if (!li->isPreformatted()) m_t << "\n";␊ |
610 | }␊ |
611 | ␊ |
612 | template<class T> ␊ |
613 | bool isFirstChildNode(T *parent, DocNode *node)␊ |
614 | {␊ |
615 | return parent->children().getFirst()==node;␊ |
616 | }␊ |
617 | ␊ |
618 | template<class T> ␊ |
619 | bool isLastChildNode(T *parent, DocNode *node)␊ |
620 | {␊ |
621 | return parent->children().getLast()==node;␊ |
622 | }␊ |
623 | ␊ |
624 | bool isSeparatedParagraph(DocSimpleSect *parent,DocPara *par)␊ |
625 | {␊ |
626 | QList<DocNode> nodes = parent->children();␊ |
627 | int i = nodes.findRef(par);␊ |
628 | if (i==-1) return FALSE;␊ |
629 | int count = parent->children().count();␊ |
630 | if (count>1 && i==0)␊ |
631 | {␊ |
632 | if (nodes.at(i+1)->kind()==DocNode::Kind_SimpleSectSep)␊ |
633 | {␊ |
634 | return TRUE;␊ |
635 | }␊ |
636 | }␊ |
637 | else if (count>1 && i==count-1)␊ |
638 | {␊ |
639 | if (nodes.at(i-1)->kind()==DocNode::Kind_SimpleSectSep)␊ |
640 | {␊ |
641 | return TRUE;␊ |
642 | }␊ |
643 | }␊ |
644 | else if (count>2 && i>0 && i<count-1)␊ |
645 | {␊ |
646 | if (nodes.at(i-1)->kind()==DocNode::Kind_SimpleSectSep &&␊ |
647 | nodes.at(i+1)->kind()==DocNode::Kind_SimpleSectSep)␊ |
648 | {␊ |
649 | return TRUE;␊ |
650 | }␊ |
651 | }␊ |
652 | return FALSE;␊ |
653 | }␊ |
654 | ␊ |
655 | static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)␊ |
656 | {␊ |
657 | int t=0;␊ |
658 | isFirst=FALSE;␊ |
659 | isLast=FALSE;␊ |
660 | if (p && p->parent())␊ |
661 | {␊ |
662 | switch (p->parent()->kind()) ␊ |
663 | {␊ |
664 | case DocNode::Kind_AutoListItem:␊ |
665 | isFirst=TRUE;␊ |
666 | isLast =TRUE;␊ |
667 | t=1; // not used␊ |
668 | break;␊ |
669 | case DocNode::Kind_SimpleListItem:␊ |
670 | isFirst=TRUE;␊ |
671 | isLast =TRUE;␊ |
672 | t=1; // not used␊ |
673 | break;␊ |
674 | case DocNode::Kind_ParamList:␊ |
675 | isFirst=TRUE;␊ |
676 | isLast =TRUE;␊ |
677 | t=1; // not used␊ |
678 | break;␊ |
679 | case DocNode::Kind_HtmlListItem:␊ |
680 | isFirst=isFirstChildNode((DocHtmlListItem*)p->parent(),p);␊ |
681 | isLast =isLastChildNode ((DocHtmlListItem*)p->parent(),p);␊ |
682 | if (isFirst) t=1;␊ |
683 | if (isLast) t=3;␊ |
684 | break;␊ |
685 | case DocNode::Kind_SecRefItem:␊ |
686 | isFirst=isFirstChildNode((DocSecRefItem*)p->parent(),p);␊ |
687 | isLast =isLastChildNode ((DocSecRefItem*)p->parent(),p);␊ |
688 | if (isFirst) t=1;␊ |
689 | if (isLast) t=3;␊ |
690 | break;␊ |
691 | case DocNode::Kind_HtmlDescData:␊ |
692 | isFirst=isFirstChildNode((DocHtmlDescData*)p->parent(),p);␊ |
693 | isLast =isLastChildNode ((DocHtmlDescData*)p->parent(),p);␊ |
694 | if (isFirst) t=2;␊ |
695 | if (isLast) t=4;␊ |
696 | break;␊ |
697 | case DocNode::Kind_XRefItem:␊ |
698 | isFirst=isFirstChildNode((DocXRefItem*)p->parent(),p);␊ |
699 | isLast =isLastChildNode ((DocXRefItem*)p->parent(),p);␊ |
700 | if (isFirst) t=2;␊ |
701 | if (isLast) t=4;␊ |
702 | break;␊ |
703 | case DocNode::Kind_HtmlCell:␊ |
704 | isFirst=isFirstChildNode((DocHtmlCell*)p->parent(),p);␊ |
705 | isLast =isLastChildNode ((DocHtmlCell*)p->parent(),p);␊ |
706 | if (isFirst) t=5;␊ |
707 | if (isLast) t=6;␊ |
708 | break;␊ |
709 | case DocNode::Kind_SimpleSect:␊ |
710 | isFirst=isFirstChildNode((DocSimpleSect*)p->parent(),p);␊ |
711 | isLast =isLastChildNode ((DocSimpleSect*)p->parent(),p);␊ |
712 | if (isFirst) t=2;␊ |
713 | if (isLast) t=4;␊ |
714 | if (isSeparatedParagraph((DocSimpleSect*)p->parent(),p))␊ |
715 | // if the paragraph is enclosed with separators it will␊ |
716 | // be included in <dd>..</dd> so avoid addition paragraph␊ |
717 | // markers␊ |
718 | {␊ |
719 | isFirst=isLast=TRUE;␊ |
720 | }␊ |
721 | break;␊ |
722 | default:␊ |
723 | break;␊ |
724 | }␊ |
725 | //printf("para=%p parent()->kind=%d isFirst=%d isLast=%d t=%d\n",␊ |
726 | // p,p->parent()->kind(),isFirst,isLast,t);␊ |
727 | }␊ |
728 | return t;␊ |
729 | }␊ |
730 | ␊ |
731 | void HtmlDocVisitor::visitPre(DocPara *p) ␊ |
732 | {␊ |
733 | if (m_hide) return;␊ |
734 | ␊ |
735 | //printf("DocPara::visitPre: parent of kind %d ",␊ |
736 | // p->parent() ? p->parent()->kind() : -1);␊ |
737 | ␊ |
738 | bool needsTag = FALSE;␊ |
739 | if (p && p->parent()) ␊ |
740 | {␊ |
741 | switch (p->parent()->kind()) ␊ |
742 | {␊ |
743 | case DocNode::Kind_Section:␊ |
744 | case DocNode::Kind_Internal:␊ |
745 | case DocNode::Kind_HtmlListItem:␊ |
746 | case DocNode::Kind_HtmlDescData:␊ |
747 | case DocNode::Kind_HtmlCell:␊ |
748 | case DocNode::Kind_SimpleListItem:␊ |
749 | case DocNode::Kind_AutoListItem:␊ |
750 | case DocNode::Kind_SimpleSect:␊ |
751 | case DocNode::Kind_XRefItem:␊ |
752 | case DocNode::Kind_Copy:␊ |
753 | needsTag = TRUE;␊ |
754 | break;␊ |
755 | case DocNode::Kind_Root:␊ |
756 | needsTag = !((DocRoot*)p->parent())->singleLine();␊ |
757 | break;␊ |
758 | default:␊ |
759 | needsTag = FALSE;␊ |
760 | }␊ |
761 | }␊ |
762 | ␊ |
763 | // if the first element of a paragraph is something that should be outside of␊ |
764 | // the paragraph (<ul>,<dl>,<table>,..) then that will already started the ␊ |
765 | // paragraph and we don't need to do it here␊ |
766 | uint nodeIndex = 0;␊ |
767 | if (p && nodeIndex<p->children().count())␊ |
768 | {␊ |
769 | while (nodeIndex<p->children().count() && ␊ |
770 | p->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace)␊ |
771 | {␊ |
772 | nodeIndex++;␊ |
773 | }␊ |
774 | if (nodeIndex<p->children().count())␊ |
775 | {␊ |
776 | DocNode *n = p->children().at(nodeIndex);␊ |
777 | if (mustBeOutsideParagraph(n))␊ |
778 | {␊ |
779 | needsTag = FALSE;␊ |
780 | }␊ |
781 | }␊ |
782 | }␊ |
783 | ␊ |
784 | // check if this paragraph is the first or last child of a <li> or <dd>.␊ |
785 | // this allows us to mark the tag with a special class so we can␊ |
786 | // fix the otherwise ugly spacing.␊ |
787 | int t;␊ |
788 | static const char *contexts[7] = ␊ |
789 | { "", // 0␊ |
790 | " class=\"startli\"", // 1␊ |
791 | " class=\"startdd\"", // 2␊ |
792 | " class=\"endli\"", // 3␊ |
793 | " class=\"enddd\"", // 4␊ |
794 | " class=\"starttd\"", // 5␊ |
795 | " class=\"endtd\"" // 6␊ |
796 | };␊ |
797 | bool isFirst;␊ |
798 | bool isLast;␊ |
799 | t = getParagraphContext(p,isFirst,isLast);␊ |
800 | //printf("startPara first=%d last=%d\n",isFirst,isLast);␊ |
801 | if (isFirst && isLast) needsTag=FALSE;␊ |
802 | ␊ |
803 | //printf(" needsTag=%d\n",needsTag);␊ |
804 | // write the paragraph tag (if needed)␊ |
805 | if (needsTag) m_t << "<p" << contexts[t] << ">";␊ |
806 | }␊ |
807 | ␊ |
808 | void HtmlDocVisitor::visitPost(DocPara *p)␊ |
809 | {␊ |
810 | // if (m_hide) return;␊ |
811 | // if (!p->isLast() && // omit <p> for last paragraph␊ |
812 | // !(p->parent() && // and for parameter sections␊ |
813 | // p->parent()->kind()==DocNode::Kind_ParamSect␊ |
814 | // ) ␊ |
815 | // ) ␊ |
816 | // {␊ |
817 | // m_t << "<p>\n";␊ |
818 | // }␊ |
819 | ␊ |
820 | bool needsTag = FALSE;␊ |
821 | if (p && p->parent()) ␊ |
822 | {␊ |
823 | switch (p->parent()->kind()) ␊ |
824 | {␊ |
825 | case DocNode::Kind_Section:␊ |
826 | case DocNode::Kind_Internal:␊ |
827 | case DocNode::Kind_HtmlListItem:␊ |
828 | case DocNode::Kind_HtmlDescData:␊ |
829 | case DocNode::Kind_HtmlCell:␊ |
830 | case DocNode::Kind_SimpleListItem:␊ |
831 | case DocNode::Kind_AutoListItem:␊ |
832 | case DocNode::Kind_SimpleSect:␊ |
833 | case DocNode::Kind_XRefItem:␊ |
834 | case DocNode::Kind_Copy:␊ |
835 | needsTag = TRUE;␊ |
836 | break;␊ |
837 | case DocNode::Kind_Root:␊ |
838 | needsTag = !((DocRoot*)p->parent())->singleLine();␊ |
839 | break;␊ |
840 | default:␊ |
841 | needsTag = FALSE;␊ |
842 | }␊ |
843 | }␊ |
844 | ␊ |
845 | QCString context;␊ |
846 | // if the last element of a paragraph is something that should be outside of␊ |
847 | // the paragraph (<ul>,<dl>,<table>) then that will already have ended the ␊ |
848 | // paragraph and we don't need to do it here␊ |
849 | int nodeIndex = p->children().count()-1;␊ |
850 | if (p && nodeIndex>=0)␊ |
851 | {␊ |
852 | while (nodeIndex>=0 && p->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace)␊ |
853 | {␊ |
854 | nodeIndex--;␊ |
855 | }␊ |
856 | if (nodeIndex>=0)␊ |
857 | {␊ |
858 | DocNode *n = p->children().at(nodeIndex);␊ |
859 | if (mustBeOutsideParagraph(n))␊ |
860 | {␊ |
861 | needsTag = FALSE;␊ |
862 | }␊ |
863 | }␊ |
864 | }␊ |
865 | ␊ |
866 | bool isFirst;␊ |
867 | bool isLast;␊ |
868 | getParagraphContext(p,isFirst,isLast);␊ |
869 | //printf("endPara first=%d last=%d\n",isFirst,isLast);␊ |
870 | if (isFirst && isLast) needsTag=FALSE;␊ |
871 | ␊ |
872 | //printf("DocPara::visitPost needsTag=%d\n",needsTag);␊ |
873 | ␊ |
874 | if (needsTag) m_t << "</p>\n";␊ |
875 | ␊ |
876 | }␊ |
877 | ␊ |
878 | void HtmlDocVisitor::visitPre(DocRoot *)␊ |
879 | {␊ |
880 | }␊ |
881 | ␊ |
882 | void HtmlDocVisitor::visitPost(DocRoot *)␊ |
883 | {␊ |
884 | }␊ |
885 | ␊ |
886 | void HtmlDocVisitor::visitPre(DocSimpleSect *s)␊ |
887 | {␊ |
888 | if (m_hide) return;␊ |
889 | forceEndParagraph(s);␊ |
890 | m_t << "<dl class=\"" << s->typeString() << "\"><dt><b>";␊ |
891 | switch(s->type())␊ |
892 | {␊ |
893 | case DocSimpleSect::See: ␊ |
894 | m_t << theTranslator->trSeeAlso(); break;␊ |
895 | case DocSimpleSect::Return: ␊ |
896 | m_t << theTranslator->trReturns(); break;␊ |
897 | case DocSimpleSect::Author: ␊ |
898 | m_t << theTranslator->trAuthor(TRUE,TRUE); break;␊ |
899 | case DocSimpleSect::Authors: ␊ |
900 | m_t << theTranslator->trAuthor(TRUE,FALSE); break;␊ |
901 | case DocSimpleSect::Version: ␊ |
902 | m_t << theTranslator->trVersion(); break;␊ |
903 | case DocSimpleSect::Since: ␊ |
904 | m_t << theTranslator->trSince(); break;␊ |
905 | case DocSimpleSect::Date: ␊ |
906 | m_t << theTranslator->trDate(); break;␊ |
907 | case DocSimpleSect::Note: ␊ |
908 | m_t << theTranslator->trNote(); break;␊ |
909 | case DocSimpleSect::Warning:␊ |
910 | m_t << theTranslator->trWarning(); break;␊ |
911 | case DocSimpleSect::Pre:␊ |
912 | m_t << theTranslator->trPrecondition(); break;␊ |
913 | case DocSimpleSect::Post:␊ |
914 | m_t << theTranslator->trPostcondition(); break;␊ |
915 | case DocSimpleSect::Invar:␊ |
916 | m_t << theTranslator->trInvariant(); break;␊ |
917 | case DocSimpleSect::Remark:␊ |
918 | m_t << theTranslator->trRemarks(); break;␊ |
919 | case DocSimpleSect::Attention:␊ |
920 | m_t << theTranslator->trAttention(); break;␊ |
921 | case DocSimpleSect::User: break;␊ |
922 | case DocSimpleSect::Rcs: break;␊ |
923 | case DocSimpleSect::Unknown: break;␊ |
924 | }␊ |
925 | ␊ |
926 | // special case 1: user defined title␊ |
927 | if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)␊ |
928 | {␊ |
929 | m_t << ":</b></dt><dd>";␊ |
930 | }␊ |
931 | }␊ |
932 | ␊ |
933 | void HtmlDocVisitor::visitPost(DocSimpleSect *s)␊ |
934 | {␊ |
935 | if (m_hide) return;␊ |
936 | m_t << "</dd></dl>\n";␊ |
937 | forceStartParagraph(s);␊ |
938 | }␊ |
939 | ␊ |
940 | void HtmlDocVisitor::visitPre(DocTitle *)␊ |
941 | {␊ |
942 | }␊ |
943 | ␊ |
944 | void HtmlDocVisitor::visitPost(DocTitle *)␊ |
945 | {␊ |
946 | if (m_hide) return;␊ |
947 | m_t << "</b></dt><dd>";␊ |
948 | }␊ |
949 | ␊ |
950 | void HtmlDocVisitor::visitPre(DocSimpleList *sl)␊ |
951 | {␊ |
952 | if (m_hide) return;␊ |
953 | forceEndParagraph(sl);␊ |
954 | m_t << "<ul>";␊ |
955 | if (!sl->isPreformatted()) m_t << "\n";␊ |
956 | ␊ |
957 | }␊ |
958 | ␊ |
959 | void HtmlDocVisitor::visitPost(DocSimpleList *sl)␊ |
960 | {␊ |
961 | if (m_hide) return;␊ |
962 | m_t << "</ul>";␊ |
963 | if (!sl->isPreformatted()) m_t << "\n";␊ |
964 | forceStartParagraph(sl);␊ |
965 | }␊ |
966 | ␊ |
967 | void HtmlDocVisitor::visitPre(DocSimpleListItem *)␊ |
968 | {␊ |
969 | if (m_hide) return;␊ |
970 | m_t << "<li>";␊ |
971 | }␊ |
972 | ␊ |
973 | void HtmlDocVisitor::visitPost(DocSimpleListItem *li) ␊ |
974 | {␊ |
975 | if (m_hide) return;␊ |
976 | m_t << "</li>";␊ |
977 | if (!li->isPreformatted()) m_t << "\n";␊ |
978 | }␊ |
979 | ␊ |
980 | void HtmlDocVisitor::visitPre(DocSection *s)␊ |
981 | {␊ |
982 | if (m_hide) return;␊ |
983 | forceEndParagraph(s);␊ |
984 | m_t << "<h" << s->level()+1 << ">";␊ |
985 | m_t << "<a class=\"anchor\" id=\"" << s->anchor();␊ |
986 | m_t << "\"></a>" << endl;␊ |
987 | filter(convertCharEntitiesToUTF8(s->title().data()));␊ |
988 | m_t << "</h" << s->level()+1 << ">\n";␊ |
989 | }␊ |
990 | ␊ |
991 | void HtmlDocVisitor::visitPost(DocSection *s) ␊ |
992 | {␊ |
993 | forceStartParagraph(s);␊ |
994 | }␊ |
995 | ␊ |
996 | void HtmlDocVisitor::visitPre(DocHtmlList *s)␊ |
997 | {␊ |
998 | if (m_hide) return;␊ |
999 | forceEndParagraph(s);␊ |
1000 | if (s->type()==DocHtmlList::Ordered) ␊ |
1001 | {␊ |
1002 | m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n"; ␊ |
1003 | }␊ |
1004 | else ␊ |
1005 | {␊ |
1006 | m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n";␊ |
1007 | }␊ |
1008 | }␊ |
1009 | ␊ |
1010 | void HtmlDocVisitor::visitPost(DocHtmlList *s) ␊ |
1011 | {␊ |
1012 | if (m_hide) return;␊ |
1013 | if (s->type()==DocHtmlList::Ordered) ␊ |
1014 | {␊ |
1015 | m_t << "</ol>"; ␊ |
1016 | }␊ |
1017 | else␊ |
1018 | { ␊ |
1019 | m_t << "</ul>";␊ |
1020 | }␊ |
1021 | if (!s->isPreformatted()) m_t << "\n";␊ |
1022 | forceStartParagraph(s);␊ |
1023 | }␊ |
1024 | ␊ |
1025 | void HtmlDocVisitor::visitPre(DocHtmlListItem *i)␊ |
1026 | {␊ |
1027 | if (m_hide) return;␊ |
1028 | m_t << "<li" << htmlAttribsToString(i->attribs()) << ">";␊ |
1029 | if (!i->isPreformatted()) m_t << "\n";␊ |
1030 | }␊ |
1031 | ␊ |
1032 | void HtmlDocVisitor::visitPost(DocHtmlListItem *) ␊ |
1033 | {␊ |
1034 | if (m_hide) return;␊ |
1035 | m_t << "</li>\n";␊ |
1036 | }␊ |
1037 | ␊ |
1038 | void HtmlDocVisitor::visitPre(DocHtmlDescList *dl)␊ |
1039 | {␊ |
1040 | if (m_hide) return;␊ |
1041 | forceEndParagraph(dl);␊ |
1042 | m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n";␊ |
1043 | }␊ |
1044 | ␊ |
1045 | void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) ␊ |
1046 | {␊ |
1047 | if (m_hide) return;␊ |
1048 | m_t << "</dl>\n";␊ |
1049 | forceStartParagraph(dl);␊ |
1050 | }␊ |
1051 | ␊ |
1052 | void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt)␊ |
1053 | {␊ |
1054 | if (m_hide) return;␊ |
1055 | m_t << "<dt" << htmlAttribsToString(dt->attribs()) << ">";␊ |
1056 | }␊ |
1057 | ␊ |
1058 | void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) ␊ |
1059 | {␊ |
1060 | if (m_hide) return;␊ |
1061 | m_t << "</dt>\n";␊ |
1062 | }␊ |
1063 | ␊ |
1064 | void HtmlDocVisitor::visitPre(DocHtmlDescData *dd)␊ |
1065 | {␊ |
1066 | if (m_hide) return;␊ |
1067 | m_t << "<dd" << htmlAttribsToString(dd->attribs()) << ">";␊ |
1068 | }␊ |
1069 | ␊ |
1070 | void HtmlDocVisitor::visitPost(DocHtmlDescData *) ␊ |
1071 | {␊ |
1072 | if (m_hide) return;␊ |
1073 | m_t << "</dd>\n";␊ |
1074 | }␊ |
1075 | ␊ |
1076 | void HtmlDocVisitor::visitPre(DocHtmlTable *t)␊ |
1077 | {␊ |
1078 | if (m_hide) return;␊ |
1079 | ␊ |
1080 | forceEndParagraph(t);␊ |
1081 | ␊ |
1082 | QString attrs = htmlAttribsToString(t->attribs());␊ |
1083 | if (attrs.isEmpty())␊ |
1084 | {␊ |
1085 | m_t << "<table class=\"doxtable\">\n";␊ |
1086 | }␊ |
1087 | else␊ |
1088 | {␊ |
1089 | m_t << "<table " << htmlAttribsToString(t->attribs()) << ">\n";␊ |
1090 | }␊ |
1091 | }␊ |
1092 | ␊ |
1093 | void HtmlDocVisitor::visitPost(DocHtmlTable *t) ␊ |
1094 | {␊ |
1095 | if (m_hide) return;␊ |
1096 | m_t << "</table>\n";␊ |
1097 | forceStartParagraph(t);␊ |
1098 | }␊ |
1099 | ␊ |
1100 | void HtmlDocVisitor::visitPre(DocHtmlRow *tr)␊ |
1101 | {␊ |
1102 | if (m_hide) return;␊ |
1103 | m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n";␊ |
1104 | }␊ |
1105 | ␊ |
1106 | void HtmlDocVisitor::visitPost(DocHtmlRow *) ␊ |
1107 | {␊ |
1108 | if (m_hide) return;␊ |
1109 | m_t << "</tr>\n";␊ |
1110 | }␊ |
1111 | ␊ |
1112 | void HtmlDocVisitor::visitPre(DocHtmlCell *c)␊ |
1113 | {␊ |
1114 | if (m_hide) return;␊ |
1115 | if (c->isHeading()) ␊ |
1116 | {␊ |
1117 | m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; ␊ |
1118 | }␊ |
1119 | else ␊ |
1120 | {␊ |
1121 | m_t << "<td" << htmlAttribsToString(c->attribs()) << ">";␊ |
1122 | }␊ |
1123 | }␊ |
1124 | ␊ |
1125 | void HtmlDocVisitor::visitPost(DocHtmlCell *c) ␊ |
1126 | {␊ |
1127 | if (m_hide) return;␊ |
1128 | if (c->isHeading()) m_t << "</th>"; else m_t << "</td>";␊ |
1129 | }␊ |
1130 | ␊ |
1131 | void HtmlDocVisitor::visitPre(DocHtmlCaption *c)␊ |
1132 | {␊ |
1133 | if (m_hide) return;␊ |
1134 | bool hasAlign = FALSE;␊ |
1135 | HtmlAttribListIterator li(c->attribs());␊ |
1136 | HtmlAttrib *att;␊ |
1137 | for (li.toFirst();(att=li.current());++li)␊ |
1138 | {␊ |
1139 | if (att->name=="align") hasAlign=TRUE;␊ |
1140 | }␊ |
1141 | m_t << "<caption" << htmlAttribsToString(c->attribs());␊ |
1142 | if (!hasAlign) m_t << " align=\"bottom\"";␊ |
1143 | m_t << ">";␊ |
1144 | }␊ |
1145 | ␊ |
1146 | void HtmlDocVisitor::visitPost(DocHtmlCaption *) ␊ |
1147 | {␊ |
1148 | if (m_hide) return;␊ |
1149 | m_t << "</caption>\n";␊ |
1150 | }␊ |
1151 | ␊ |
1152 | void HtmlDocVisitor::visitPre(DocInternal *)␊ |
1153 | {␊ |
1154 | if (m_hide) return;␊ |
1155 | //forceEndParagraph(i);␊ |
1156 | //m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>" << endl;␊ |
1157 | }␊ |
1158 | ␊ |
1159 | void HtmlDocVisitor::visitPost(DocInternal *) ␊ |
1160 | {␊ |
1161 | if (m_hide) return;␊ |
1162 | //forceStartParagraph(i);␊ |
1163 | }␊ |
1164 | ␊ |
1165 | void HtmlDocVisitor::visitPre(DocHRef *href)␊ |
1166 | {␊ |
1167 | if (m_hide) return;␊ |
1168 | m_t << "<a href=\"" << convertToXML(href->url()) << "\""␊ |
1169 | << htmlAttribsToString(href->attribs()) << ">";␊ |
1170 | }␊ |
1171 | ␊ |
1172 | void HtmlDocVisitor::visitPost(DocHRef *) ␊ |
1173 | {␊ |
1174 | if (m_hide) return;␊ |
1175 | m_t << "</a>";␊ |
1176 | }␊ |
1177 | ␊ |
1178 | void HtmlDocVisitor::visitPre(DocHtmlHeader *header)␊ |
1179 | {␊ |
1180 | if (m_hide) return;␊ |
1181 | forceEndParagraph(header);␊ |
1182 | m_t << "<h" << header->level() ␊ |
1183 | << htmlAttribsToString(header->attribs()) << ">";␊ |
1184 | }␊ |
1185 | ␊ |
1186 | void HtmlDocVisitor::visitPost(DocHtmlHeader *header) ␊ |
1187 | {␊ |
1188 | if (m_hide) return;␊ |
1189 | m_t << "</h" << header->level() << ">\n";␊ |
1190 | forceStartParagraph(header);␊ |
1191 | }␊ |
1192 | ␊ |
1193 | void HtmlDocVisitor::visitPre(DocImage *img)␊ |
1194 | {␊ |
1195 | if (img->type()==DocImage::Html)␊ |
1196 | {␊ |
1197 | forceEndParagraph(img);␊ |
1198 | if (m_hide) return;␊ |
1199 | QString baseName=img->name();␊ |
1200 | int i;␊ |
1201 | if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)␊ |
1202 | {␊ |
1203 | baseName=baseName.right(baseName.length()-i-1);␊ |
1204 | }␊ |
1205 | m_t << "<div class=\"image\">" << endl;␊ |
1206 | m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\"" ␊ |
1207 | << baseName << "\"" << htmlAttribsToString(img->attribs()) ␊ |
1208 | << "/>" << endl;␊ |
1209 | if (img->hasCaption())␊ |
1210 | {␊ |
1211 | m_t << "<div class=\"caption\">" << endl;␊ |
1212 | }␊ |
1213 | }␊ |
1214 | else // other format -> skip␊ |
1215 | {␊ |
1216 | pushEnabled();␊ |
1217 | m_hide=TRUE;␊ |
1218 | }␊ |
1219 | }␊ |
1220 | ␊ |
1221 | void HtmlDocVisitor::visitPost(DocImage *img) ␊ |
1222 | {␊ |
1223 | if (img->type()==DocImage::Html)␊ |
1224 | {␊ |
1225 | if (m_hide) return;␊ |
1226 | if (img->hasCaption())␊ |
1227 | {␊ |
1228 | m_t << "</div>";␊ |
1229 | }␊ |
1230 | m_t << "</div>" << endl;␊ |
1231 | forceStartParagraph(img);␊ |
1232 | }␊ |
1233 | else // other format␊ |
1234 | {␊ |
1235 | popEnabled();␊ |
1236 | }␊ |
1237 | }␊ |
1238 | ␊ |
1239 | void HtmlDocVisitor::visitPre(DocDotFile *df)␊ |
1240 | {␊ |
1241 | if (m_hide) return;␊ |
1242 | m_t << "<div class=\"dotgraph\">" << endl;␊ |
1243 | writeDotFile(df->file(),df->relPath(),df->context());␊ |
1244 | if (df->hasCaption())␊ |
1245 | { ␊ |
1246 | m_t << "<div class=\"caption\">" << endl;␊ |
1247 | }␊ |
1248 | }␊ |
1249 | ␊ |
1250 | void HtmlDocVisitor::visitPost(DocDotFile *df) ␊ |
1251 | {␊ |
1252 | if (m_hide) return;␊ |
1253 | if (df->hasCaption())␊ |
1254 | {␊ |
1255 | m_t << "</div>" << endl;␊ |
1256 | }␊ |
1257 | m_t << "</div>" << endl;␊ |
1258 | }␊ |
1259 | ␊ |
1260 | void HtmlDocVisitor::visitPre(DocMscFile *df)␊ |
1261 | {␊ |
1262 | if (m_hide) return;␊ |
1263 | m_t << "<div class=\"mscgraph\">" << endl;␊ |
1264 | writeMscFile(df->file(),df->relPath(),df->context());␊ |
1265 | if (df->hasCaption())␊ |
1266 | { ␊ |
1267 | m_t << "<div class=\"caption\">" << endl;␊ |
1268 | }␊ |
1269 | }␊ |
1270 | void HtmlDocVisitor::visitPost(DocMscFile *df) ␊ |
1271 | {␊ |
1272 | if (m_hide) return;␊ |
1273 | if (df->hasCaption())␊ |
1274 | {␊ |
1275 | m_t << "</div>" << endl;␊ |
1276 | }␊ |
1277 | m_t << "</div>" << endl;␊ |
1278 | }␊ |
1279 | ␊ |
1280 | void HtmlDocVisitor::visitPre(DocLink *lnk)␊ |
1281 | {␊ |
1282 | if (m_hide) return;␊ |
1283 | startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor());␊ |
1284 | }␊ |
1285 | ␊ |
1286 | void HtmlDocVisitor::visitPost(DocLink *) ␊ |
1287 | {␊ |
1288 | if (m_hide) return;␊ |
1289 | endLink();␊ |
1290 | }␊ |
1291 | ␊ |
1292 | void HtmlDocVisitor::visitPre(DocRef *ref)␊ |
1293 | {␊ |
1294 | if (m_hide) return;␊ |
1295 | if (!ref->file().isEmpty()) ␊ |
1296 | {␊ |
1297 | startLink(ref->ref(),ref->file(),ref->relPath(),ref->anchor());␊ |
1298 | }␊ |
1299 | if (!ref->hasLinkText()) filter(ref->targetTitle());␊ |
1300 | }␊ |
1301 | ␊ |
1302 | void HtmlDocVisitor::visitPost(DocRef *ref) ␊ |
1303 | {␊ |
1304 | if (m_hide) return;␊ |
1305 | if (!ref->file().isEmpty()) endLink();␊ |
1306 | //m_t << " ";␊ |
1307 | }␊ |
1308 | ␊ |
1309 | void HtmlDocVisitor::visitPre(DocSecRefItem *ref)␊ |
1310 | {␊ |
1311 | if (m_hide) return;␊ |
1312 | QString refName=ref->file();␊ |
1313 | if (refName.right(Doxygen::htmlFileExtension.length())!=␊ |
1314 | QString(Doxygen::htmlFileExtension))␊ |
1315 | {␊ |
1316 | refName+=Doxygen::htmlFileExtension;␊ |
1317 | }␊ |
1318 | m_t << "<li><a href=\"" << refName << "#" << ref->anchor() << "\">";␊ |
1319 | ␊ |
1320 | }␊ |
1321 | ␊ |
1322 | void HtmlDocVisitor::visitPost(DocSecRefItem *) ␊ |
1323 | {␊ |
1324 | if (m_hide) return;␊ |
1325 | m_t << "</a></li>\n";␊ |
1326 | }␊ |
1327 | ␊ |
1328 | void HtmlDocVisitor::visitPre(DocSecRefList *s)␊ |
1329 | {␊ |
1330 | if (m_hide) return;␊ |
1331 | forceEndParagraph(s);␊ |
1332 | m_t << "<div class=\"multicol\">" << endl;␊ |
1333 | m_t << "<ul>" << endl;␊ |
1334 | }␊ |
1335 | ␊ |
1336 | void HtmlDocVisitor::visitPost(DocSecRefList *s) ␊ |
1337 | {␊ |
1338 | if (m_hide) return;␊ |
1339 | m_t << "</ul>" << endl;␊ |
1340 | m_t << "</div>" << endl;␊ |
1341 | forceStartParagraph(s);␊ |
1342 | }␊ |
1343 | ␊ |
1344 | //void HtmlDocVisitor::visitPre(DocLanguage *l)␊ |
1345 | //{␊ |
1346 | // QString langId = Config_getEnum("OUTPUT_LANGUAGE");␊ |
1347 | // if (l->id().lower()!=langId.lower())␊ |
1348 | // {␊ |
1349 | // pushEnabled();␊ |
1350 | // m_hide = TRUE;␊ |
1351 | // }␊ |
1352 | //}␊ |
1353 | //␊ |
1354 | //void HtmlDocVisitor::visitPost(DocLanguage *l) ␊ |
1355 | //{␊ |
1356 | // QString langId = Config_getEnum("OUTPUT_LANGUAGE");␊ |
1357 | // if (l->id().lower()!=langId.lower())␊ |
1358 | // {␊ |
1359 | // popEnabled();␊ |
1360 | // }␊ |
1361 | //}␊ |
1362 | ␊ |
1363 | void HtmlDocVisitor::visitPre(DocParamSect *s)␊ |
1364 | {␊ |
1365 | if (m_hide) return;␊ |
1366 | forceEndParagraph(s);␊ |
1367 | m_t << "<dl><dt><b>";␊ |
1368 | QCString className;␊ |
1369 | switch(s->type())␊ |
1370 | {␊ |
1371 | case DocParamSect::Param: ␊ |
1372 | m_t << theTranslator->trParameters(); ␊ |
1373 | className="params";␊ |
1374 | break;␊ |
1375 | case DocParamSect::RetVal: ␊ |
1376 | m_t << theTranslator->trReturnValues(); ␊ |
1377 | className="retval";␊ |
1378 | break;␊ |
1379 | case DocParamSect::Exception: ␊ |
1380 | m_t << theTranslator->trExceptions(); ␊ |
1381 | className="exception";␊ |
1382 | break;␊ |
1383 | case DocParamSect::TemplateParam: ␊ |
1384 | /* TODO: add this ␊ |
1385 | m_t << theTranslator->trTemplateParam(); break;␊ |
1386 | */␊ |
1387 | m_t << "Template Parameters"; break;␊ |
1388 | className="tparams";␊ |
1389 | default:␊ |
1390 | ASSERT(0);␊ |
1391 | }␊ |
1392 | m_t << ":";␊ |
1393 | m_t << "</b></dt><dd>" << endl;␊ |
1394 | m_t << " <table class=\"" << className << "\">" << endl;␊ |
1395 | }␊ |
1396 | ␊ |
1397 | void HtmlDocVisitor::visitPost(DocParamSect *s)␊ |
1398 | {␊ |
1399 | if (m_hide) return;␊ |
1400 | m_t << " </table>" << endl;␊ |
1401 | m_t << " </dd>" << endl;␊ |
1402 | m_t << "</dl>" << endl;␊ |
1403 | forceStartParagraph(s);␊ |
1404 | }␊ |
1405 | ␊ |
1406 | void HtmlDocVisitor::visitPre(DocParamList *pl)␊ |
1407 | {␊ |
1408 | //printf("DocParamList::visitPre\n");␊ |
1409 | if (m_hide) return;␊ |
1410 | m_t << " <tr>";␊ |
1411 | DocParamSect *sect = 0;␊ |
1412 | if (pl->parent()->kind()==DocNode::Kind_ParamSect)␊ |
1413 | {␊ |
1414 | sect=(DocParamSect*)pl->parent();␊ |
1415 | }␊ |
1416 | if (sect && sect->hasInOutSpecifier())␊ |
1417 | {␊ |
1418 | m_t << "<td class=\"paramdir\">";␊ |
1419 | if (pl->direction()!=DocParamSect::Unspecified)␊ |
1420 | {␊ |
1421 | m_t << "[";␊ |
1422 | if (pl->direction()==DocParamSect::In)␊ |
1423 | {␊ |
1424 | m_t << "in";␊ |
1425 | }␊ |
1426 | else if (pl->direction()==DocParamSect::Out)␊ |
1427 | {␊ |
1428 | m_t << "out";␊ |
1429 | }␊ |
1430 | else if (pl->direction()==DocParamSect::InOut)␊ |
1431 | {␊ |
1432 | m_t << "in,out";␊ |
1433 | }␊ |
1434 | m_t << "]";␊ |
1435 | }␊ |
1436 | m_t << "</td>";␊ |
1437 | }␊ |
1438 | if (sect && sect->hasTypeSpecifier())␊ |
1439 | {␊ |
1440 | m_t << "<td class=\"paramtype\">";␊ |
1441 | QListIterator<DocNode> li(pl->paramTypes());␊ |
1442 | DocNode *type;␊ |
1443 | bool first=TRUE;␊ |
1444 | for (li.toFirst();(type=li.current());++li)␊ |
1445 | {␊ |
1446 | if (!first) m_t << " | "; else first=FALSE;␊ |
1447 | if (type->kind()==DocNode::Kind_Word)␊ |
1448 | {␊ |
1449 | visit((DocWord*)type); ␊ |
1450 | }␊ |
1451 | else if (type->kind()==DocNode::Kind_LinkedWord)␊ |
1452 | {␊ |
1453 | visit((DocLinkedWord*)type); ␊ |
1454 | }␊ |
1455 | }␊ |
1456 | m_t << "</td>";␊ |
1457 | }␊ |
1458 | m_t << "<td class=\"paramname\">";␊ |
1459 | //QStrListIterator li(pl->parameters());␊ |
1460 | //const char *s;␊ |
1461 | QListIterator<DocNode> li(pl->parameters());␊ |
1462 | DocNode *param;␊ |
1463 | bool first=TRUE;␊ |
1464 | for (li.toFirst();(param=li.current());++li)␊ |
1465 | {␊ |
1466 | if (!first) m_t << ","; else first=FALSE;␊ |
1467 | if (param->kind()==DocNode::Kind_Word)␊ |
1468 | {␊ |
1469 | visit((DocWord*)param); ␊ |
1470 | }␊ |
1471 | else if (param->kind()==DocNode::Kind_LinkedWord)␊ |
1472 | {␊ |
1473 | visit((DocLinkedWord*)param); ␊ |
1474 | }␊ |
1475 | }␊ |
1476 | m_t << "</td><td>";␊ |
1477 | }␊ |
1478 | ␊ |
1479 | void HtmlDocVisitor::visitPost(DocParamList *)␊ |
1480 | {␊ |
1481 | //printf("DocParamList::visitPost\n");␊ |
1482 | if (m_hide) return;␊ |
1483 | m_t << "</td></tr>" << endl;␊ |
1484 | }␊ |
1485 | ␊ |
1486 | void HtmlDocVisitor::visitPre(DocXRefItem *x)␊ |
1487 | {␊ |
1488 | if (m_hide) return;␊ |
1489 | forceEndParagraph(x);␊ |
1490 | bool anonymousEnum = x->file()=="@";␊ |
1491 | if (!anonymousEnum)␊ |
1492 | {␊ |
1493 | m_t << "<dl class=\"" << x->key() << "\"><dt><b><a class=\"el\" href=\"" ␊ |
1494 | << x->relPath() << x->file() << Doxygen::htmlFileExtension ␊ |
1495 | << "#" << x->anchor() << "\">";␊ |
1496 | }␊ |
1497 | else ␊ |
1498 | {␊ |
1499 | m_t << "<dl class=\"" << x->key() << "\"><dt><b>";␊ |
1500 | }␊ |
1501 | filter(x->title());␊ |
1502 | m_t << ":";␊ |
1503 | if (!anonymousEnum) m_t << "</a>";␊ |
1504 | m_t << "</b></dt><dd>";␊ |
1505 | }␊ |
1506 | ␊ |
1507 | void HtmlDocVisitor::visitPost(DocXRefItem *x)␊ |
1508 | {␊ |
1509 | if (m_hide) return;␊ |
1510 | m_t << "</dd></dl>" << endl;␊ |
1511 | forceStartParagraph(x);␊ |
1512 | }␊ |
1513 | ␊ |
1514 | void HtmlDocVisitor::visitPre(DocInternalRef *ref)␊ |
1515 | {␊ |
1516 | if (m_hide) return;␊ |
1517 | startLink(0,ref->file(),ref->relPath(),ref->anchor());␊ |
1518 | }␊ |
1519 | ␊ |
1520 | void HtmlDocVisitor::visitPost(DocInternalRef *) ␊ |
1521 | {␊ |
1522 | if (m_hide) return;␊ |
1523 | endLink();␊ |
1524 | m_t << " ";␊ |
1525 | }␊ |
1526 | ␊ |
1527 | void HtmlDocVisitor::visitPre(DocCopy *)␊ |
1528 | {␊ |
1529 | }␊ |
1530 | ␊ |
1531 | void HtmlDocVisitor::visitPost(DocCopy *)␊ |
1532 | {␊ |
1533 | }␊ |
1534 | ␊ |
1535 | void HtmlDocVisitor::visitPre(DocText *)␊ |
1536 | {␊ |
1537 | }␊ |
1538 | ␊ |
1539 | void HtmlDocVisitor::visitPost(DocText *)␊ |
1540 | {␊ |
1541 | }␊ |
1542 | ␊ |
1543 | void HtmlDocVisitor::filter(const char *str)␊ |
1544 | { ␊ |
1545 | if (str==0) return;␊ |
1546 | const char *p=str;␊ |
1547 | char c;␊ |
1548 | while (*p)␊ |
1549 | {␊ |
1550 | c=*p++;␊ |
1551 | switch(c)␊ |
1552 | {␊ |
1553 | case '<': m_t << "<"; break;␊ |
1554 | case '>': m_t << ">"; break;␊ |
1555 | case '&': m_t << "&"; break;␊ |
1556 | default: m_t << c;␊ |
1557 | }␊ |
1558 | }␊ |
1559 | }␊ |
1560 | ␊ |
1561 | /// Escape basic entities to produce a valid CDATA attribute value,␊ |
1562 | /// assume that the outer quoting will be using the double quote "␊ |
1563 | void HtmlDocVisitor::filterQuotedCdataAttr(const char* str)␊ |
1564 | {␊ |
1565 | if (str==0) return;␊ |
1566 | const char *p=str;␊ |
1567 | char c;␊ |
1568 | while (*p)␊ |
1569 | {␊ |
1570 | c=*p++;␊ |
1571 | switch(c)␊ |
1572 | {␊ |
1573 | case '&': m_t << "&"; break;␊ |
1574 | case '"': m_t << """; break;␊ |
1575 | // For SGML compliance, and given the SGML declaration for HTML syntax,␊ |
1576 | // it's enough to replace these two, provided that the declaration␊ |
1577 | // for the HTML version we generate (and as supported by the browser)␊ |
1578 | // specifies that all the other symbols used in rawVal are␊ |
1579 | // within the right charachter class (i.e., they're not␊ |
1580 | // some multinational weird charachters not in the BASESET).␊ |
1581 | // We assume that 1) the browser will support whatever is remaining␊ |
1582 | // in the formula and 2) the TeX formulae are generally governed␊ |
1583 | // by even stricter charachter restrictions so it should be enough.␊ |
1584 | //␊ |
1585 | // On some incompliant browsers, additional translation of␊ |
1586 | // '>' and '<' into ">" and "<", respectively, might be needed;␊ |
1587 | // but I'm unaware of particular modern (last 4 years) versions␊ |
1588 | // with such problems, so let's not do it for performance.␊ |
1589 | // Also, some brousers will (wrongly) not process the entity references␊ |
1590 | // inside the attribute value and show the &...; form instead, ␊ |
1591 | // so we won't create entites unless necessary to minimize clutter there.␊ |
1592 | // --vassilii ␊ |
1593 | default: m_t << c;␊ |
1594 | }␊ |
1595 | }␊ |
1596 | }␊ |
1597 | ␊ |
1598 | void HtmlDocVisitor::startLink(const QCString &ref,const QCString &file,␊ |
1599 | const QCString &relPath,const QCString &anchor,␊ |
1600 | const QCString &tooltip)␊ |
1601 | {␊ |
1602 | if (!ref.isEmpty()) // link to entity imported via tag file␊ |
1603 | {␊ |
1604 | m_t << "<a class=\"elRef\" ";␊ |
1605 | m_t << externalLinkTarget() << externalRef(relPath,ref,FALSE);␊ |
1606 | }␊ |
1607 | else // local link␊ |
1608 | {␊ |
1609 | m_t << "<a class=\"el\" ";␊ |
1610 | }␊ |
1611 | m_t << "href=\"";␊ |
1612 | m_t << externalRef(relPath,ref,TRUE);␊ |
1613 | if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension;␊ |
1614 | if (!anchor.isEmpty()) m_t << "#" << anchor;␊ |
1615 | m_t << "\"";␊ |
1616 | if (!tooltip.isEmpty()) m_t << " title=\"" << tooltip << "\"";␊ |
1617 | m_t << ">";␊ |
1618 | }␊ |
1619 | ␊ |
1620 | void HtmlDocVisitor::endLink()␊ |
1621 | {␊ |
1622 | m_t << "</a>";␊ |
1623 | }␊ |
1624 | ␊ |
1625 | void HtmlDocVisitor::pushEnabled()␊ |
1626 | {␊ |
1627 | m_enabled.push(new bool(m_hide));␊ |
1628 | }␊ |
1629 | ␊ |
1630 | void HtmlDocVisitor::popEnabled()␊ |
1631 | {␊ |
1632 | bool *v=m_enabled.pop();␊ |
1633 | ASSERT(v!=0);␊ |
1634 | m_hide = *v;␊ |
1635 | delete v;␊ |
1636 | }␊ |
1637 | ␊ |
1638 | void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath,␊ |
1639 | const QCString &context)␊ |
1640 | {␊ |
1641 | QCString baseName=fn;␊ |
1642 | int i;␊ |
1643 | if ((i=baseName.findRev('/'))!=-1)␊ |
1644 | {␊ |
1645 | baseName=baseName.right(baseName.length()-i-1);␊ |
1646 | }␊ |
1647 | if ((i=baseName.find('.'))!=-1) // strip extension␊ |
1648 | {␊ |
1649 | baseName=baseName.left(i);␊ |
1650 | }␊ |
1651 | baseName.prepend("dot_");␊ |
1652 | QCString outDir = Config_getString("HTML_OUTPUT");␊ |
1653 | writeDotGraphFromFile(fn,outDir,baseName,BITMAP);␊ |
1654 | writeDotImageMapFromFile(m_t,fn,outDir,relPath,baseName,context);␊ |
1655 | }␊ |
1656 | ␊ |
1657 | void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath,␊ |
1658 | const QCString &context)␊ |
1659 | {␊ |
1660 | QCString baseName=fileName;␊ |
1661 | int i;␊ |
1662 | if ((i=baseName.findRev('/'))!=-1) // strip path␊ |
1663 | {␊ |
1664 | baseName=baseName.right(baseName.length()-i-1);␊ |
1665 | }␊ |
1666 | if ((i=baseName.find('.'))!=-1) // strip extension␊ |
1667 | {␊ |
1668 | baseName=baseName.left(i);␊ |
1669 | }␊ |
1670 | baseName.prepend("msc_");␊ |
1671 | QCString outDir = Config_getString("HTML_OUTPUT");␊ |
1672 | writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);␊ |
1673 | writeMscImageMapFromFile(m_t,fileName,outDir,relPath,baseName,context);␊ |
1674 | }␊ |
1675 | ␊ |
1676 | /** Used for items found inside a paragraph, which due to XHTML restrictions␊ |
1677 | * have to be outside of the paragraph. This method will forcefully end␊ |
1678 | * the current paragraph and forceStartParagraph() will restart it.␊ |
1679 | */␊ |
1680 | void HtmlDocVisitor::forceEndParagraph(DocNode *n)␊ |
1681 | {␊ |
1682 | //printf("forceEndParagraph(%p) %d\n",n,n->kind());␊ |
1683 | if (n->parent() && n->parent()->kind()==DocNode::Kind_Para)␊ |
1684 | {␊ |
1685 | DocPara *para = (DocPara*)n->parent();␊ |
1686 | int nodeIndex = para->children().findRef(n);␊ |
1687 | nodeIndex--;␊ |
1688 | if (nodeIndex<0) return; // first node␊ |
1689 | while (nodeIndex>=0 && ␊ |
1690 | para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace␊ |
1691 | )␊ |
1692 | {␊ |
1693 | nodeIndex--;␊ |
1694 | }␊ |
1695 | if (nodeIndex>=0)␊ |
1696 | {␊ |
1697 | DocNode *n = para->children().at(nodeIndex);␊ |
1698 | //printf("n=%p kind=%d outside=%d\n",n,n->kind(),mustBeOutsideParagraph(n));␊ |
1699 | if (mustBeOutsideParagraph(n)) return;␊ |
1700 | }␊ |
1701 | ␊ |
1702 | bool isFirst;␊ |
1703 | bool isLast;␊ |
1704 | getParagraphContext(para,isFirst,isLast);␊ |
1705 | //printf("forceEnd first=%d last=%d\n",isFirst,isLast);␊ |
1706 | if (isFirst && isLast) return;␊ |
1707 | ␊ |
1708 | m_t << "</p>" << endl;␊ |
1709 | }␊ |
1710 | }␊ |
1711 | ␊ |
1712 | /** Used for items found inside a paragraph, which due to XHTML restrictions␊ |
1713 | * have to be outside of the paragraph. This method will forcefully start␊ |
1714 | * the paragraph, that was previously ended by forceEndParagraph().␊ |
1715 | */␊ |
1716 | void HtmlDocVisitor::forceStartParagraph(DocNode *n)␊ |
1717 | {␊ |
1718 | //printf("forceStartParagraph(%p) %d\n",n,n->kind());␊ |
1719 | if (n->parent() && n->parent()->kind()==DocNode::Kind_Para) // if we are inside a paragraph␊ |
1720 | {␊ |
1721 | DocPara *para = (DocPara*)n->parent();␊ |
1722 | int nodeIndex = para->children().findRef(n);␊ |
1723 | int numNodes = para->children().count();␊ |
1724 | nodeIndex++;␊ |
1725 | if (nodeIndex==numNodes) return; // last node␊ |
1726 | while (nodeIndex<numNodes && ␊ |
1727 | para->children().at(nodeIndex)->kind()==DocNode::Kind_WhiteSpace␊ |
1728 | )␊ |
1729 | {␊ |
1730 | nodeIndex++;␊ |
1731 | }␊ |
1732 | if (nodeIndex<numNodes)␊ |
1733 | {␊ |
1734 | DocNode *n = para->children().at(nodeIndex);␊ |
1735 | if (mustBeOutsideParagraph(n)) return;␊ |
1736 | }␊ |
1737 | else␊ |
1738 | {␊ |
1739 | return; // only whitespace at the end!␊ |
1740 | }␊ |
1741 | ␊ |
1742 | bool isFirst;␊ |
1743 | bool isLast;␊ |
1744 | getParagraphContext(para,isFirst,isLast);␊ |
1745 | //printf("forceStart first=%d last=%d\n",isFirst,isLast);␊ |
1746 | if (isFirst && isLast) return;␊ |
1747 | ␊ |
1748 | m_t << "<p>";␊ |
1749 | }␊ |
1750 | }␊ |
1751 | ␊ |
1752 |