2011333aae4b3d64fcf985601e5307df609d2725
[platform/upstream/doxygen.git] / src / docbookgen.cpp
1 /******************************************************************************
2 *
3
4 *
5 * Copyright (C) 1997-2014 by Dimitri van Heesch.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation under the terms of the GNU General Public License is hereby
9 * granted. No representations are made about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
11 * See the GNU General Public License for more details.
12 *
13 * Documents produced by Doxygen are derivative works derived from the
14 * input used in their production; they are not affected by this license.
15 *
16 */
17
18 #include <stdlib.h>
19
20 #include <qdir.h>
21 #include <qfile.h>
22 #include <qtextstream.h>
23 #include <qintdict.h>
24 #include "docbookgen.h"
25 #include "doxygen.h"
26 #include "message.h"
27 #include "config.h"
28 #include "classlist.h"
29 #include "util.h"
30 #include "defargs.h"
31 #include "outputgen.h"
32 #include "dot.h"
33 #include "pagedef.h"
34 #include "filename.h"
35 #include "version.h"
36 #include "docbookvisitor.h"
37 #include "docparser.h"
38 #include "language.h"
39 #include "parserintf.h"
40 #include "arguments.h"
41 #include "memberlist.h"
42 #include "groupdef.h"
43 #include "memberdef.h"
44 #include "namespacedef.h"
45 #include "membername.h"
46 #include "membergroup.h"
47 #include "dirdef.h"
48 #include "section.h"
49
50 // no debug info
51 #define Docbook_DB(x) do {} while(0)
52 // debug to stdout
53 //#define Docbook_DB(x) printf x
54 // debug inside output
55 //#define Docbook_DB(x) QCString __t;__t.sprintf x;m_t << __t
56
57 //------------------
58
59 class DocbookSectionMapper : public QIntDict<char>
60 {
61   public:
62     DocbookSectionMapper() : QIntDict<char>(47)
63   {
64     insert(MemberListType_pubTypes,"public-type");
65     insert(MemberListType_pubMethods,"public-func");
66     insert(MemberListType_pubAttribs,"public-attrib");
67     insert(MemberListType_pubSlots,"public-slot");
68     insert(MemberListType_signals,"signal");
69     insert(MemberListType_dcopMethods,"dcop-func");
70     insert(MemberListType_properties,"property");
71     insert(MemberListType_events,"event");
72     insert(MemberListType_pubStaticMethods,"public-static-func");
73     insert(MemberListType_pubStaticAttribs,"public-static-attrib");
74     insert(MemberListType_proTypes,"protected-type");
75     insert(MemberListType_proMethods,"protected-func");
76     insert(MemberListType_proAttribs,"protected-attrib");
77     insert(MemberListType_proSlots,"protected-slot");
78     insert(MemberListType_proStaticMethods,"protected-static-func");
79     insert(MemberListType_proStaticAttribs,"protected-static-attrib");
80     insert(MemberListType_pacTypes,"package-type");
81     insert(MemberListType_pacMethods,"package-func");
82     insert(MemberListType_pacAttribs,"package-attrib");
83     insert(MemberListType_pacStaticMethods,"package-static-func");
84     insert(MemberListType_pacStaticAttribs,"package-static-attrib");
85     insert(MemberListType_priTypes,"private-type");
86     insert(MemberListType_priMethods,"private-func");
87     insert(MemberListType_priAttribs,"private-attrib");
88     insert(MemberListType_priSlots,"private-slot");
89     insert(MemberListType_priStaticMethods,"private-static-func");
90     insert(MemberListType_priStaticAttribs,"private-static-attrib");
91     insert(MemberListType_friends,"friend");
92     insert(MemberListType_related,"related");
93     insert(MemberListType_decDefineMembers,"define");
94     insert(MemberListType_decProtoMembers,"prototype");
95     insert(MemberListType_decTypedefMembers,"typedef");
96     insert(MemberListType_decEnumMembers,"enum");
97     insert(MemberListType_decFuncMembers,"func");
98     insert(MemberListType_decVarMembers,"var");
99   }
100 };
101
102 static DocbookSectionMapper g_docbookSectionMapper;
103
104
105 inline void writeDocbookString(FTextStream &t,const char *s)
106 {
107   t << convertToXML(s);
108 }
109
110 inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col)
111 {
112   char c;
113   while ((c=*s++))
114   {
115     switch(c)
116     {
117       case '\t':
118         {
119           static int tabSize = Config_getInt("TAB_SIZE");
120           int spacesToNextTabStop = tabSize - (col%tabSize);
121           col+=spacesToNextTabStop;
122           while (spacesToNextTabStop--) t << "&#32;";
123           break;
124         }
125       case ' ':  t << "&#32;"; col++;  break;
126       case '<':  t << "&lt;"; col++;   break;
127       case '>':  t << "&gt;"; col++;   break;
128       case '&':  t << "&amp;"; col++;  break;
129       case '\'': t << "&apos;"; col++; break;
130       case '"':  t << "&quot;"; col++; break;
131       default:   t << c; col++;        break;
132     }
133   }
134 }
135
136 static void writeDocbookHeaderMainpage(FTextStream &t)
137 {
138   t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
139   t << "<chapter xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
140 }
141
142 static void writeDocbookHeader_ID(FTextStream &t, QCString id)
143 {
144   t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
145   t << "<section xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"" << id << "\">" << endl;
146 }
147
148 void writeDocbookLink(FTextStream &t,const char * /*extRef*/,const char *compoundId,
149     const char *anchorId,const char * text,const char * /*tooltip*/)
150 {
151   t << "<link linkend=\"" << compoundId;
152   if (anchorId) t << "_1" << anchorId;
153   t << "\"";
154   t << ">";
155   writeDocbookString(t,text);
156   t << "</link>";
157 }
158
159 class TextGeneratorDocbookImpl : public TextGeneratorIntf
160 {
161   public:
162     TextGeneratorDocbookImpl(FTextStream &t): m_t(t) {}
163     void writeString(const char *s,bool /*keepSpaces*/) const
164     {
165       writeDocbookString(m_t,s);
166     }
167     void writeBreak(int) const {}
168     void writeLink(const char *extRef,const char *file,
169         const char *anchor,const char *text
170         ) const
171     {
172       writeDocbookLink(m_t,extRef,file,anchor,text,0);
173     }
174   private:
175     FTextStream &m_t;
176 };
177
178 class DocbookCodeGenerator : public CodeOutputInterface
179 {
180   public:
181     DocbookCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1),
182     m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE) {}
183     virtual ~DocbookCodeGenerator() {}
184
185     void codify(const char *text)
186     {
187       Docbook_DB(("(codify \"%s\")\n",text));
188       writeDocbookCodeString(m_t,text,col);
189     }
190     void writeCodeLink(const char *ref,const char *file,
191         const char *anchor,const char *name,
192         const char *tooltip)
193     {
194       Docbook_DB(("(writeCodeLink)\n"));
195       writeDocbookLink(m_t,ref,file,anchor,name,tooltip);
196       col+=strlen(name);
197     }
198     void writeTooltip(const char *, const DocLinkInfo &, const char *,
199                       const char *, const SourceLinkInfo &, const SourceLinkInfo &
200                      )
201     {
202       Docbook_DB(("(writeToolTip)\n"));
203     }
204     void startCodeLine(bool)
205     {
206       Docbook_DB(("(startCodeLine)\n"));
207       if (m_lineNumber!=-1)
208       {
209         if (!m_refId.isEmpty())
210         {
211           m_t << "<link linkend=\"" << m_refId << "\">";
212         }
213         m_t << m_lineNumber;
214         if (!m_refId.isEmpty())
215         {
216           m_t << "</link>";
217         }
218       }
219       m_insideCodeLine=TRUE;
220       col=0;
221     }
222     void endCodeLine()
223     {
224       m_t << endl;
225       Docbook_DB(("(endCodeLine)\n"));
226       m_lineNumber = -1;
227       m_refId.resize(0);
228       m_external.resize(0);
229       m_insideCodeLine=FALSE;
230     }
231     void startFontClass(const char * /*colorClass*/)
232     {
233       Docbook_DB(("(startFontClass)\n"));
234       m_t << "<emphasis>"; // non DocBook
235       m_insideSpecialHL=TRUE;
236     }
237     void endFontClass()
238     {
239       Docbook_DB(("(endFontClass)\n"));
240       m_t << "</emphasis>"; // non DocBook
241       m_insideSpecialHL=FALSE;
242     }
243     void writeCodeAnchor(const char *)
244     {
245       Docbook_DB(("(writeCodeAnchor)\n"));
246     }
247     void writeLineNumber(const char *extRef,const char *compId,
248         const char *anchorId,int l)
249     {
250       Docbook_DB(("(writeLineNumber)\n"));
251       // we remember the information provided here to use it
252       // at the <codeline> start tag.
253       m_lineNumber = l;
254       if (compId)
255       {
256         m_refId=compId;
257         if (anchorId) m_refId+=(QCString)"_1"+anchorId;
258         m_isMemberRef = anchorId!=0;
259         if (extRef) m_external=extRef;
260       }
261     }
262     void setCurrentDoc(Definition *,const char *,bool)
263     {
264     }
265     void addWord(const char *,bool)
266     {
267     }
268     void finish()
269     {
270       if (m_insideCodeLine) endCodeLine();
271     }
272
273   private:
274     FTextStream &m_t;
275     QCString m_refId;
276     QCString m_external;
277     int m_lineNumber;
278     bool m_isMemberRef;
279     int col;
280     bool m_insideCodeLine;
281     bool m_insideSpecialHL;
282 };
283
284
285 static void writeTemplateArgumentList(ArgumentList *al,
286     FTextStream &t,
287     Definition *scope,
288     FileDef *fileScope,
289     int indent)
290 {
291   QCString indentStr;
292   indentStr.fill(' ',indent);
293   if (al)
294   {
295     t << indentStr << "<templateparamlist>" << endl;
296     ArgumentListIterator ali(*al);
297     Argument *a;
298     for (ali.toFirst();(a=ali.current());++ali)
299     {
300       t << indentStr << "  <param>" << endl;
301       if (!a->type.isEmpty())
302       {
303         t << indentStr <<  "    <type>";
304         linkifyText(TextGeneratorDocbookImpl(t),scope,fileScope,0,a->type);
305         t << "</type>" << endl;
306       }
307       if (!a->name.isEmpty())
308       {
309         t << indentStr <<  "    <declname>" << a->name << "</declname>" << endl;
310         t << indentStr <<  "    <defname>" << a->name << "</defname>" << endl;
311       }
312       if (!a->defval.isEmpty())
313       {
314         t << indentStr << "    <defval>";
315         linkifyText(TextGeneratorDocbookImpl(t),scope,fileScope,0,a->defval);
316         t << "</defval>" << endl;
317       }
318       t << indentStr << "  </param>" << endl;
319     }
320     t << indentStr << "</templateparamlist>" << endl;
321   }
322 }
323
324 static void writeTemplateList(ClassDef *cd,FTextStream &t)
325 {
326   writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4);
327 }
328
329 static void writeDocbookDocBlock(FTextStream &t,
330     const QCString &fileName,
331     int lineNr,
332     Definition *scope,
333     MemberDef * md,
334     const QCString &text)
335 {
336   QCString stext = text.stripWhiteSpace();
337   if (stext.isEmpty()) return;
338   // convert the documentation string into an abstract syntax tree
339   DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE);
340   // create a code generator
341   DocbookCodeGenerator *docbookCodeGen = new DocbookCodeGenerator(t);
342   // create a parse tree visitor for Docbook
343   DocbookDocVisitor *visitor = new DocbookDocVisitor(t,*docbookCodeGen);
344   // visit all nodes
345   root->accept(visitor);
346   // clean up
347   delete visitor;
348   delete docbookCodeGen;
349   delete root;
350 }
351
352 void writeDocbookCodeBlock(FTextStream &t,FileDef *fd)
353 {
354   ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension());
355   SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension());
356   pIntf->resetCodeParserState();
357   DocbookCodeGenerator *docbookGen = new DocbookCodeGenerator(t);
358   pIntf->parseCode(*docbookGen,  // codeOutIntf
359       0,           // scopeName
360       fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES")),
361       langExt,     // lang
362       FALSE,       // isExampleBlock
363       0,           // exampleName
364       fd,          // fileDef
365       -1,          // startLine
366       -1,          // endLine
367       FALSE,       // inlineFragement
368       0,           // memberDef
369       TRUE         // showLineNumbers
370       );
371   docbookGen->finish();
372   delete docbookGen;
373 }
374
375 static QCString classOutputFileBase(ClassDef *cd)
376 {
377   //static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES");
378   //if (inlineGroupedClasses && cd->partOfGroups()!=0)
379   return cd->getOutputFileBase();
380   //else
381   //  return cd->getOutputFileBase();
382 }
383
384 static QCString memberOutputFileBase(MemberDef *md)
385 {
386   //static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES");
387   //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0)
388   //  return md->getClassDef()->getDocbookOutputFileBase();
389   //else
390   //  return md->getOutputFileBase();
391   return md->getOutputFileBase();
392 }
393
394
395 static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *def, bool detailed=0)
396 {
397
398   // + declaration/definition arg lists
399   // + reimplements
400   // + reimplementedBy
401   // + exceptions
402   // + const/volatile specifiers
403   // - examples
404   // + source definition
405   // + source references
406   // + source referenced by
407   // - body code
408   // + template arguments
409   //     (templateArguments(), definitionTemplateParameterLists())
410   // - call graph
411
412   // enum values are written as part of the enum
413   if (md->memberType()==MemberType_EnumValue) return;
414   if (md->isHidden()) return;
415   //if (md->name().at(0)=='@') return; // anonymous member
416
417   // group members are only visible in their group
418   //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
419   QCString memType;
420   switch (md->memberType())
421   {
422     case MemberType_Define:      memType="define";    break;
423     case MemberType_Function:    memType="function";  break;
424     case MemberType_Variable:    memType="variable";  break;
425     case MemberType_Typedef:     memType="typedef";   break;
426     case MemberType_Enumeration: memType="enum";      break;
427     case MemberType_EnumValue:   ASSERT(0);           break;
428     case MemberType_Signal:      memType="signal";    break;
429     case MemberType_Slot:        memType="slot";      break;
430     case MemberType_Friend:      memType="friend";    break;
431     case MemberType_DCOP:        memType="dcop";      break;
432     case MemberType_Property:    memType="property";  break;
433     case MemberType_Event:       memType="event";     break;
434     case MemberType_Interface:   memType="interface"; break;
435     case MemberType_Service:     memType="service";   break;
436   }
437   QCString scopeName;
438   if (md->getClassDef())
439   {
440     scopeName=md->getClassDef()->name();
441   }
442   else if (md->getNamespaceDef())
443   {
444     scopeName=md->getNamespaceDef()->name();
445   }
446   if (detailed==0) 
447   {
448     t << "            <para>" << endl;
449     t << "                <itemizedlist>" << endl;
450     t << "                    <listitem>" << endl;
451     //enum
452     bool closePara=TRUE;
453     if (md->memberType()==MemberType_Enumeration) 
454     {
455       MemberList *enumFields = md->enumFieldList();
456       t << "                            <para>" << memType << " <link linkend=\"";
457       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
458       {
459         t << md->getGroupDef()->getOutputFileBase();
460       }
461       else
462       {
463         t << memberOutputFileBase(md);
464       }
465       t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>";
466       if (enumFields!=0) 
467       {
468         MemberListIterator emli(*enumFields);
469         MemberDef *emd;
470         t << "{";
471         int cnt=0;
472         for (emli.toFirst();(emd=emli.current());++emli) 
473         {
474           if (cnt!=0) 
475           {
476             t << ", ";
477           }
478           t << "<link linkend=\"" << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">";
479           writeDocbookString(t,emd->name());
480           t << "</link>";
481           if (!emd->initializer().isEmpty()) 
482           {
483             t << "=";
484             writeDocbookString(t,emd->initializer());
485           }
486           cnt++;
487         }
488         t << "}";
489       }
490     }
491     else if (md->memberType()==MemberType_Define) 
492     {
493       t << "                            <para>" << "#" << memType << " <link linkend=\"";
494       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
495       {
496         t << md->getGroupDef()->getOutputFileBase();
497       }
498       else
499       {
500         t << memberOutputFileBase(md);
501       }
502       t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>";
503       if (!md->initializer().isEmpty() && md->initializer().length()<2000) 
504       {
505         t << " ";
506         linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->initializer());
507       }
508       if (md->briefDescription()) 
509       {
510         t << "<para><emphasis>";
511         writeDocbookString(t,md->briefDescription());
512         t << "</emphasis></para>" << endl;
513       }
514     }
515     else if (md->memberType()==MemberType_Variable) 
516     {
517       if (md->getClassDef()) 
518       {
519         t << "                        <para>" << convertToXML(md->declaration());
520         if (md->briefDescription()) 
521         {
522           t << "<para><emphasis>";
523           writeDocbookString(t,md->briefDescription());
524           t << "</emphasis></para>";
525         }
526       } 
527       else 
528       {
529         t << "                        <para>";
530         linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
531         t << " <link linkend=\"";
532         if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
533         {
534           t << md->getGroupDef()->getOutputFileBase();
535         }
536         else
537         {
538           t << memberOutputFileBase(md);
539         }
540         t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>";
541       }
542     }
543     else if (md->memberType()==MemberType_Typedef) 
544     {
545       t << "                            <para>" << memType;
546       t << " ";
547       linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
548       t << " ";
549       t << " <link linkend=\"";
550       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
551       {
552         t << md->getGroupDef()->getOutputFileBase();
553       }
554       else
555       {
556         t << memberOutputFileBase(md);
557       }
558       t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>";
559     }
560     else if (md->memberType()==MemberType_Function) 
561     {
562       t << "                        <para>";
563       linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString());
564       t << " <link linkend=\"";
565       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
566       {
567         t << md->getGroupDef()->getOutputFileBase();
568       }
569       else
570       {
571         t << memberOutputFileBase(md);
572       }
573       t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>";
574       t << " (" << endl;
575       ArgumentList *declAl = md->declArgumentList();
576       ArgumentList *defAl = md->argumentList();
577       if (declAl && declAl->count()>0)
578       {
579         ArgumentListIterator declAli(*declAl);
580         ArgumentListIterator defAli(*defAl);
581         Argument *a;
582         int cnt=0;
583         for (declAli.toFirst();(a=declAli.current());++declAli)
584         {
585           if (cnt!=0) 
586           {
587             t << ", ";
588           }
589           if (!a->type.isEmpty())
590           {
591             linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,a->type);
592           }
593           t << " ";
594           if (!a->name.isEmpty())
595           {
596             writeDocbookString(t,a->name);
597           }
598           cnt++;
599         }
600       }
601       t << ")";
602     }
603     else
604     {
605       closePara = FALSE;
606     }
607     if (closePara) t << "</para>" << endl;
608     t << "                    </listitem>" << endl;
609     t << "                </itemizedlist>" << endl;
610     t << "            </para>" << endl;
611   } 
612   else 
613   {
614     if (md->memberType()==MemberType_Enumeration) 
615     {
616       MemberList *enumFields = md->enumFieldList();
617       t << "            <section xml:id=\"";
618       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
619       {
620         t << md->getGroupDef()->getOutputFileBase();
621       }
622       else
623       {
624         t << memberOutputFileBase(md);
625       }
626       t << "_1" << md->anchor() << "\">" << endl;
627       t << "               <title>" << memType << " " << convertToXML(md->name()) << " " << "</title>" << endl;
628       t << "               ";
629       writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
630       t << endl;
631       if (enumFields!=0) 
632       {
633         MemberListIterator emli(*enumFields);
634         MemberDef *emd;
635         t << "               <formalpara>" << endl;
636         t << "                    <title>Enumerator:</title>" << endl;
637         t << "                    <variablelist>" << endl;
638         for (emli.toFirst();(emd=emli.current());++emli) 
639         {
640           t << "                        <varlistentry xml:id=\"";
641           t << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">" << endl;
642           t << "                            <term>";
643           writeDocbookString(t,emd->name());
644           t << "</term>" << endl;
645           t << "                            <listitem>" << endl;
646           t << "                                <para>";
647           writeDocbookString(t,emd->briefDescription());
648           t << "</para>" << endl;
649           t << "                            </listitem>" << endl;
650           t << "                        </varlistentry>" << endl;
651         }
652         t << "                     </variablelist>" << endl;
653         t << "                </formalpara>" << endl;
654         t << "                <para>";
655         t << "Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << endl;
656         t << "                    <programlisting>" << endl;
657         t << "{" << endl;
658         for (emli.toFirst();(emd=emli.current());++emli) 
659         {
660           writeDocbookString(t,emd->name());
661           if (!emd->initializer().isEmpty()) 
662           {
663             t << "=";
664             writeDocbookString(t,emd->initializer());
665           }
666           t << ", " << endl;
667         }
668         t << "}" << convertToXML(md->name()) << ";" << endl;
669         t << "                    </programlisting>" << endl;
670         t << "                </para>" << endl;
671         t << "            </section>" << endl;
672       }
673     }
674     else if (md->memberType()==MemberType_Typedef) 
675     {
676       t << "            <section xml:id=\"";
677       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
678       {
679         t << md->getGroupDef()->getOutputFileBase();
680       }
681       else
682       {
683         t << memberOutputFileBase(md);
684       }
685       t << "_1" << md->anchor() << "\">" << endl;
686       t << "                <title>" << convertToXML(md->definition()) << "</title>";
687       t << " <emphasis>";
688       writeDocbookString(t,md->briefDescription());
689       t << "</emphasis>" << endl;
690       t << "                ";
691       writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
692       t << endl;
693       t << "            </section>" << endl;
694     }
695     else if (md->memberType()==MemberType_Function) 
696     {
697       t << "            <section xml:id=\"";
698       if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
699       {
700         t << md->getGroupDef()->getOutputFileBase();
701       }
702       else
703       {
704         t << memberOutputFileBase(md);
705       }
706       t << "_1" << md->anchor() << "\">" << endl;
707       t << "                <title>" << convertToXML(md->definition()) << " " << convertToXML(md->argsString()) << "</title>";
708       t << " <emphasis>";
709       writeDocbookString(t,md->briefDescription());
710       t << "</emphasis>" << endl;
711       t << "                ";
712       writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
713       t << endl;
714       t << "            </section>" << endl;
715     }
716     else if (md->memberType()==MemberType_Define) 
717     {
718       if (md->documentation()) 
719       {
720         t << "            <section xml:id=\"";
721         if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
722         {
723           t << md->getGroupDef()->getOutputFileBase();
724         }
725         else
726         {
727           t << memberOutputFileBase(md);
728         }
729         t << "_1" << md->anchor() << "\">" << endl;
730         t << "                <title>" << convertToXML(md->definition()) << "</title>";
731         t << "                ";
732         writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
733         t << endl;
734         t << "                <para>Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << "</para>" << endl;
735         t << "                <para>The Documentation for this define was generated from the following file: </para>" << endl;
736         t << "                <para><itemizedlist><listitem><para>" << stripPath(md->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
737         t << "            </section>" << endl;
738       }
739     }
740     else if (md->memberType()==MemberType_Variable) 
741     {
742       if (md->getClassDef()) 
743       {
744         if (md->documentation()) 
745         {
746           t << "            <simplesect>" << endl;
747           t << "                <title>" << convertToXML(md->definition()) << "</title>";
748           t << "                ";
749           writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
750           t << endl;
751           t << "                <para>Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << "</para>" << endl;
752           t << "                <para>The Documentation for this struct was generated from the following file: </para>" << endl;
753           t << "                <para><itemizedlist><listitem><para>" << stripPath(md->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
754           t << "            </simplesect>" << endl;
755         }
756       }
757       else 
758       {
759         t << "            <section xml:id=\"";
760         if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
761         {
762           t << md->getGroupDef()->getOutputFileBase();
763         }
764         else
765         {
766           t << memberOutputFileBase(md);
767         }
768         t << "_1" << md->anchor() << "\">" << endl;
769         t << "                <title>" << convertToXML(md->definition()) << "</title>";
770         t << " <emphasis>";
771         writeDocbookString(t,md->briefDescription());
772         t << "</emphasis>" << endl;
773         t << "                ";
774         writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
775         t << endl;
776         t << "            </section>" << endl;
777       }
778     }
779   }
780 }
781
782 static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,const char *kind,
783     bool detailed=0, const char *header=0,const char *documentation=0)
784 {
785   if (ml==0) return;
786   MemberListIterator mli(*ml);
787   MemberDef *md;
788   int count=0;
789   int doc_count=0;
790   QCString compkind = kind;
791   QCString title, desctitle;
792
793   for (mli.toFirst();(md=mli.current());++mli) 
794   {
795     // namespace members are also inserted in the file scope, but
796     // to prevent this duplication in the Docbook output, we filter those here.
797     if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) 
798     {
799       count++;
800     }
801   }
802
803   switch (ml->listType())
804   {
805     case MemberListType_decDefineMembers:  title="Defines";             desctitle="Define Documentation";              break;
806     case MemberListType_decTypedefMembers: title="Typedefs";            desctitle="Typedef Documentation";             break;
807     case MemberListType_decEnumMembers:    title="Enumerations";        desctitle="Enumeration Type documentation";    break;
808     case MemberListType_decFuncMembers:    title="Functions";           desctitle="Function Documentation";            break;
809     case MemberListType_decVarMembers:     title="Variables";           desctitle="Variable Documentation";            break;
810     case MemberListType_pubAttribs:        title="Public Attributes";   desctitle="Member Documentation";              break;
811     case MemberListType_priAttribs:        title="Private Attributes";  desctitle="Member Documentation";              break;
812     case MemberListType_proAttribs:        title="Protected Attributes";desctitle="Member Documentation";              break;
813     default:                               title="";                    desctitle="";                                  break;
814   }
815
816   if (count==0) return; // empty list
817
818   for (mli.toFirst();(md=mli.current());++mli) 
819   {
820     if (md->documentation()) 
821     {
822       doc_count++;
823     }
824   }
825
826   if (detailed) 
827   {
828     if (desctitle) 
829     {
830       if (desctitle=="Member Documentation") 
831       {
832         if (doc_count > 0) 
833         {
834           t << "        <simplesect>" << endl;
835           t << "            <title>" << desctitle << "</title>" << endl;
836         }
837       } 
838       else if (desctitle=="Define Documentation") 
839       {
840         if (doc_count > 0) 
841         {
842           t << "        <section>" << endl;
843           t << "            <title>" << desctitle << "</title>" << endl;
844         }
845       } 
846       else 
847       {
848         t << "        <section>" << endl;
849         t << "            <title>" << desctitle << "</title>" << endl;
850       }
851     }
852   } else 
853   {
854     t << "        <simplesect>" << endl;
855     if (header) 
856     {
857       t << "            <title>" << convertToXML(header) << "</title>" << endl;
858     } 
859     else 
860     {
861       t << "            <title>" << title << "</title>" << endl;
862     }
863   }
864
865   if (documentation) 
866   {
867     t << "      <description>";
868     writeDocbookDocBlock(t,d->docFile(),d->docLine(),d,0,documentation);
869     t << "</description>" << endl;
870   }
871   for (mli.toFirst();(md=mli.current());++mli) 
872   {
873     // namespace members are also inserted in the file scope, but
874     // to prevent this duplication in the Docbook output, we filter those here.
875     if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) 
876     {
877       generateDocbookForMember(md,t,d,detailed);
878     }
879   }
880   if (detailed) 
881   {
882     if (desctitle) 
883     {
884       if (desctitle=="Member Documentation") 
885       {
886         if (doc_count > 0) 
887         {
888           t << "        </simplesect>" << endl;
889         }
890       } 
891       else if (desctitle=="Define Documentation") 
892       {
893         if (doc_count > 0) 
894         {
895           t << "        </section>" << endl;
896         }
897       } 
898       else 
899       {
900         t << "        </section>" << endl;
901       }
902     }
903   } 
904   else 
905   {
906     t << "        </simplesect>" << endl;
907   }
908 }
909
910 static void writeInnerClasses(const ClassSDict *cl,FTextStream &t)
911 {
912   if (cl)
913   {
914     ClassSDict::Iterator cli(*cl);
915     ClassDef *cd;
916     QCString title = "Classes";
917
918     if (cli.toFirst()) 
919     {
920       t << "        <simplesect>" << endl;
921       t << "            <title> " << title << " </title>" << endl;
922     }
923     for (cli.toFirst();(cd=cli.current());++cli)
924     {
925       if (!cd->isHidden() && cd->name().find('@')==-1) 
926       {
927         t << "            <para>" << endl;
928         t << "                <itemizedlist>" << endl;
929         t << "                    <listitem>" << endl;
930         t << "                        <para>" << "struct <link linkend=\"" << classOutputFileBase(cd) << "\">" << convertToXML(cd->name()) << "</link>";
931         t << "</para>" << endl;
932         t << "                    </listitem>" << endl;
933         t << "                </itemizedlist>" << endl;
934         t << "            </para>" << endl;
935       }
936     }
937     if (cli.toFirst()) 
938     {
939       t << "        </simplesect>" << endl;
940     }
941   }
942 }
943
944 static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
945 {
946   if (nl)
947   {
948     NamespaceSDict::Iterator nli(*nl);
949     NamespaceDef *nd;
950     QCString title = "Namespaces";
951
952     if (nli.toFirst()) 
953     {
954       t << "        <simplesect>" << endl;
955       t << "            <title> " << title << " </title>" << endl;
956     }
957     for (nli.toFirst();(nd=nli.current());++nli)
958     {
959       if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
960       {
961         t << "            <para>" << endl;
962         t << "                <itemizedlist>" << endl;
963         t << "                    <listitem>" << endl;
964         t << "                        <para>" << "struct <link linkend=\"" << nd->getOutputFileBase() << "\">" << convertToXML(nd->name()) << "</link>";
965         t << "</para>" << endl;
966         t << "                    </listitem>" << endl;
967         t << "                </itemizedlist>" << endl;
968         t << "            </para>" << endl;
969       }
970     }
971     if (nli.toFirst()) 
972     {
973       t << "        </simplesect>" << endl;
974     }
975   }
976 }
977
978 static void writeInnerFiles(const FileList *fl,FTextStream &t)
979 {
980   if (fl)
981   {
982     QListIterator<FileDef> fli(*fl);
983     FileDef *fd;
984     QCString title = "Files";
985
986     if (fli.toFirst()) 
987     {
988       t << "        <simplesect>" << endl;
989       t << "            <title> " << title << " </title>" << endl;
990     }
991     for (fli.toFirst();(fd=fli.current());++fli) 
992     {
993       t << "            <para>" << endl;
994       t << "                <itemizedlist>" << endl;
995       t << "                    <listitem>" << endl;
996       t << "                        <para>" << "file <link linkend=\"" << fd->getOutputFileBase() << "\">" << convertToXML(fd->name()) << "</link>";
997       t << "</para>" << endl;
998       t << "                    </listitem>" << endl;
999       t << "                </itemizedlist>" << endl;
1000       t << "            </para>" << endl;
1001     }
1002     if (fli.toFirst()) 
1003     {
1004       t << "        </simplesect>" << endl;
1005     }
1006   }
1007 }
1008
1009 static void writeInnerPages(const PageSDict *pl,FTextStream &t)
1010 {
1011   if (pl)
1012   {
1013     PageSDict::Iterator pli(*pl);
1014     PageDef *pd;
1015
1016     for (pli.toFirst();(pd=pli.current());++pli)
1017     {
1018       t << "<xi:include href=\"" << pd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"  << endl;
1019     }
1020   }
1021 }
1022
1023 static void writeInnerGroups(const GroupList *gl,FTextStream &t)
1024 {
1025   if (gl)
1026   {
1027     GroupListIterator gli(*gl);
1028     GroupDef *sgd;
1029
1030     //Docbook header tags for inner groups
1031     if (gli.toFirst()) 
1032     {
1033       t << "    <simplesect>" << endl;
1034       t << "        <title>Modules</title>" << endl;
1035       t << "    </simplesect>" << endl;
1036       t << "    <para>" << endl;
1037       t << "        <itemizedlist>" << endl;
1038     }
1039
1040     for (gli.toFirst();(sgd=gli.current());++gli)
1041     {
1042       t << "            <listitem><para><link linkend=\"" << sgd->getOutputFileBase() << "\">" << convertToXML(sgd->groupTitle()) << "</link></para></listitem>" << endl;
1043     }
1044
1045     //Docbook footer tags for inner groups
1046     if (gli.toFirst()) 
1047     {
1048       t << "        </itemizedlist>" << endl;
1049       t << "    </para>" << endl;
1050     }
1051
1052   }
1053 }
1054
1055 static void writeInnerDirs(const DirList *dl,FTextStream &t)
1056 {
1057   if (dl)
1058   {
1059     QListIterator<DirDef> subdirs(*dl);
1060     DirDef *subdir;
1061     QCString title = "Directories";
1062     if (subdirs.toFirst()) 
1063     {
1064       t << "        <simplesect>" << endl;
1065       t << "            <title> " << title << " </title>" << endl;
1066     }
1067     for (subdirs.toFirst();(subdir=subdirs.current());++subdirs)
1068     {
1069       t << "            <para>" << endl;
1070       t << "                <itemizedlist>" << endl;
1071       t << "                    <listitem>" << endl;
1072       t << "                        <para>" << "dir <link linkend=\"" << subdir->getOutputFileBase() << "\">" << convertToXML(subdir->displayName()) << "</link>";
1073       t << "</para>" << endl;
1074       t << "                    </listitem>" << endl;
1075       t << "                </itemizedlist>" << endl;
1076       t << "            </para>" << endl;
1077     }
1078     if (subdirs.toFirst()) 
1079     {
1080       t << "        </simplesect>" << endl;
1081     }
1082   }
1083 }
1084
1085 static void writeInnerGroupFiles(const GroupList *gl,FTextStream &t)
1086 {
1087   if (gl)
1088   {
1089     GroupListIterator gli(*gl);
1090     GroupDef *sgd;
1091
1092     for (gli.toFirst();(sgd=gli.current());++gli)
1093     {
1094       t << "<xi:include href=\"" << sgd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"  << endl;
1095     }
1096   }
1097 }
1098
1099 static void generateDocbookForClass(ClassDef *cd,FTextStream &ti)
1100 {
1101   // + brief description
1102   // + detailed description
1103   // + template argument list(s)
1104   // - include file
1105   // + member groups
1106   // + inheritance diagram
1107   // + list of direct super classes
1108   // + list of direct sub classes
1109   // + list of inner classes
1110   // + collaboration diagram
1111   // + list of all members
1112   // + user defined member sections
1113   // + standard member sections
1114   // + detailed member documentation
1115   // - examples using the class
1116
1117   if (cd->isReference())        return; // skip external references.
1118   if (cd->isHidden())           return; // skip hidden classes.
1119   if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
1120   if (cd->templateMaster()!=0)  return; // skip generated template instances.
1121
1122   msg("Generating Docbook output for class %s\n",cd->name().data());
1123
1124   QCString fileDocbook=cd->getOutputFileBase()+".xml";
1125   //Add the file Documentation info to index file
1126   ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1127
1128   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1129   QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml";
1130   QFile f(fileName);
1131   if (!f.open(IO_WriteOnly))
1132   {
1133     err("Cannot open file %s for writing!\n",fileName.data());
1134     return;
1135   }
1136   FTextStream t(&f);
1137   //t.setEncoding(FTextStream::UnicodeUTF8);
1138
1139   writeDocbookHeader_ID(t, classOutputFileBase(cd));
1140   t << "<title>";
1141   writeDocbookString(t,cd->name());
1142   t << " " << cd->compoundTypeString() << " Reference";
1143   t << "</title>" << endl;
1144
1145   IncludeInfo *ii=cd->includeInfo();
1146   if (ii)
1147   {
1148     QCString nm = ii->includeName;
1149     if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1150     if (!nm.isEmpty())
1151     {
1152       t << "<para>" << endl;
1153       t << "    <programlisting>#include ";
1154       if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
1155       {
1156         t << "<link linkend=\"" << ii->fileDef->getOutputFileBase() << "\">";
1157       }
1158       if (ii->local)
1159       {
1160         t << "&quot;";
1161       }
1162       else
1163       {
1164         t << "&lt;";
1165       }
1166       t << convertToXML(nm);
1167       if (ii->local)
1168       {
1169         t << "&quot;";
1170       }
1171       else
1172       {
1173         t << "&gt;";
1174       }
1175       if (ii->fileDef && !ii->fileDef->isReference())
1176       {
1177         t << "</link>";
1178       }
1179       t << "</programlisting>" << endl;
1180       t << "</para>" << endl;
1181     }
1182   }
1183
1184   writeInnerClasses(cd->getClassSDict(),t);
1185
1186   writeTemplateList(cd,t);
1187   if (cd->getMemberGroupSDict())
1188   {
1189     MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
1190     MemberGroup *mg;
1191     for (;(mg=mgli.current());++mgli)
1192     {
1193       generateDocbookSection(cd,t,mg->members(),"user-defined",0,mg->header(),
1194           mg->documentation());
1195     }
1196   }
1197
1198
1199   QListIterator<MemberList> mli(cd->getMemberLists());
1200   MemberList *ml;
1201   for (mli.toFirst();(ml=mli.current());++mli)
1202   {
1203     if ((ml->listType()&MemberListType_detailedLists)==0)
1204     {
1205       generateDocbookSection(cd,t,ml,g_docbookSectionMapper.find(ml->listType()));
1206     }
1207   }
1208   if (cd->briefDescription()) 
1209   {
1210     t << "    <simplesect>" << endl;
1211     t << "        <title>Brief Description</title>" << endl;
1212     writeDocbookDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
1213     t << "    </simplesect>" << endl;
1214   }
1215
1216   if (cd->documentation()) 
1217   {
1218     t << "        <simplesect>" << endl;
1219     t << "            <title>Detailed Description</title>" << endl;
1220     writeDocbookDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
1221     t << "                <para>Definition at line " << cd->getDefLine() << " of file " << stripPath(cd->getDefFileName()) << "</para>" << endl;
1222     t << "                <para>The Documentation for this struct was generated from the following file: </para>" << endl;
1223     t << "                <para><itemizedlist><listitem><para>" << stripPath(cd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
1224     t << "        </simplesect>" << endl;
1225   }
1226   for (mli.toFirst();(ml=mli.current());++mli)
1227   {
1228     if ((ml->listType()&MemberListType_detailedLists)==0)
1229     {
1230       generateDocbookSection(cd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
1231     }
1232   }
1233
1234   /*// TODO: Handling of Inheritance and Colloboration graph for Docbook to be implemented
1235     DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
1236     if (!inheritanceGraph.isTrivial())
1237     {
1238     t << "    <inheritancegraph>" << endl;
1239     inheritanceGraph.writeDocbook(t);
1240     t << "    </inheritancegraph>" << endl;
1241     }
1242     DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
1243     if (!collaborationGraph.isTrivial())
1244     {
1245     t << "    <collaborationgraph>" << endl;
1246     collaborationGraph.writeDocbook(t);
1247     t << "    </collaborationgraph>" << endl;
1248     }
1249     t << "    <location file=\""
1250     << cd->getDefFileName() << "\" line=\""
1251     << cd->getDefLine() << "\"";
1252     if (cd->getStartBodyLine()!=-1)
1253     {
1254     FileDef *bodyDef = cd->getBodyDef();
1255     if (bodyDef)
1256     {
1257     t << " bodyfile=\"" << bodyDef->absFilePath() << "\"";
1258     }
1259     t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\""
1260     << cd->getEndBodyLine() << "\"";
1261     }
1262     t << "/>" << endl;
1263     writeListOfAllMembers(cd,t);
1264    */
1265
1266   t << "</section>" << endl;
1267
1268 }
1269
1270 static void generateDocbookForNamespace(NamespaceDef *nd,FTextStream &ti)
1271 {
1272   // + contained class definitions
1273   // + contained namespace definitions
1274   // + member groups
1275   // + normal members
1276   // + brief desc
1277   // + detailed desc
1278   // + location
1279   // - files containing (parts of) the namespace definition
1280
1281   if (nd->isReference() || nd->isHidden()) return; // skip external references
1282
1283   QCString fileDocbook=nd->getOutputFileBase()+".xml";
1284   //Add the file Documentation info to index file
1285   ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1286
1287   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1288   QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml";
1289   QFile f(fileName);
1290   if (!f.open(IO_WriteOnly))
1291   {
1292     err("Cannot open file %s for writing!\n",fileName.data());
1293     return;
1294   }
1295   FTextStream t(&f);
1296   //t.setEncoding(FTextStream::UnicodeUTF8);
1297
1298   writeDocbookHeader_ID(t, nd->getOutputFileBase());
1299   t << "<title>";
1300   writeDocbookString(t,nd->name());
1301   t << "</title>" << endl;
1302
1303   writeInnerClasses(nd->getClassSDict(),t);
1304   writeInnerNamespaces(nd->getNamespaceSDict(),t);
1305
1306   if (nd->getMemberGroupSDict())
1307   {
1308     MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
1309     MemberGroup *mg;
1310     for (;(mg=mgli.current());++mgli)
1311     {
1312       generateDocbookSection(nd,t,mg->members(),"user-defined",0,mg->header(),
1313           mg->documentation());
1314     }
1315   }
1316
1317   QListIterator<MemberList> mli(nd->getMemberLists());
1318   MemberList *ml;
1319   for (mli.toFirst();(ml=mli.current());++mli)
1320   {
1321     if ((ml->listType()&MemberListType_declarationLists)!=0)
1322     {
1323       generateDocbookSection(nd,t,ml,g_docbookSectionMapper.find(ml->listType()));
1324     }
1325   }
1326
1327   if (nd->briefDescription()) 
1328   {
1329     t << "    <simplesect>" << endl;
1330     t << "        <title>Brief Description</title>" << endl;
1331     writeDocbookDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription());
1332     t << "    </simplesect>" << endl;
1333   }
1334
1335   if (nd->documentation()) 
1336   {
1337     t << "        <simplesect>" << endl;
1338     t << "            <title>Detailed Description</title>" << endl;
1339     writeDocbookDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation());
1340     t << "                <para>Definition at line " << nd->getDefLine() << " of file " << stripPath(nd->getDefFileName()) << "</para>" << endl;
1341     t << "                <para>The Documentation for this struct was generated from the following file: </para>" << endl;
1342     t << "                <para><itemizedlist><listitem><para>" << stripPath(nd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl;
1343     t << "        </simplesect>" << endl;
1344   }
1345   t << "</section>" << endl;
1346 }
1347
1348 static void generateDocbookForFile(FileDef *fd,FTextStream &ti)
1349 {
1350   // + includes files
1351   // + includedby files
1352   // + include graph
1353   // + included by graph
1354   // + contained class definitions
1355   // + contained namespace definitions
1356   // + member groups
1357   // + normal members
1358   // + brief desc
1359   // + detailed desc
1360   // + source code
1361   // + location
1362   // - number of lines
1363
1364   if (fd->isReference()) return; // skip external references
1365
1366   QCString fileDocbook=fd->getOutputFileBase()+".xml";
1367   //Add the file Documentation info to index file
1368   ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1369
1370   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1371   QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml";
1372
1373   QFile f(fileName);
1374   if (!f.open(IO_WriteOnly))
1375   {
1376     err("Cannot open file %s for writing!\n",fileName.data());
1377     return;
1378   }
1379   FTextStream t(&f);
1380   //t.setEncoding(FTextStream::UnicodeUTF8);
1381   writeDocbookHeader_ID(t, fd->getOutputFileBase());
1382
1383   t << "    <title>";
1384   writeDocbookString(t,fd->name());
1385   t << " File Reference";
1386   t << "</title>" << endl;
1387
1388   IncludeInfo *inc;
1389
1390   if (fd->includeFileList())
1391   {
1392     QListIterator<IncludeInfo> ili1(*fd->includeFileList());
1393     for (ili1.toFirst();(inc=ili1.current());++ili1)
1394     {
1395       t << "    <programlisting>#include ";
1396       if (inc->local)
1397       {
1398         t << "&quot;";
1399       }
1400       else
1401       {
1402         t << "&lt;";
1403       }
1404       t << convertToXML(inc->includeName);
1405       if (inc->local)
1406       {
1407         t << "&quot;";
1408       }
1409       else
1410       {
1411         t << "&gt;";
1412       }
1413       t << "</programlisting>" << endl;
1414     }
1415   }
1416
1417   if (fd->getClassSDict())
1418   {
1419     writeInnerClasses(fd->getClassSDict(),t);
1420   }
1421   if (fd->getNamespaceSDict())
1422   {
1423     writeInnerNamespaces(fd->getNamespaceSDict(),t);
1424   }
1425
1426   if (fd->getMemberGroupSDict())
1427   {
1428     MemberGroupSDict::Iterator mgli(*fd->getMemberGroupSDict());
1429     MemberGroup *mg;
1430     for (;(mg=mgli.current());++mgli)
1431     {
1432       generateDocbookSection(fd,t,mg->members(),"user-defined",0,mg->header(),
1433           mg->documentation());
1434     }
1435   }
1436
1437   QListIterator<MemberList> mli(fd->getMemberLists());
1438   MemberList *ml;
1439   for (mli.toFirst();(ml=mli.current());++mli)
1440   {
1441     if ((ml->listType()&MemberListType_declarationLists)!=0)
1442     {
1443       generateDocbookSection(fd,t,ml,g_docbookSectionMapper.find(ml->listType()));
1444     }
1445   }
1446
1447   t << "    <simplesect>" << endl;
1448   t << "        <title>Detailed Description</title>" << endl;
1449   writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription());
1450   writeDocbookDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation());
1451   t << "    <para>Definition in file " << fd->getDefFileName() << "</para>" << endl;
1452   t << "    </simplesect>" << endl;
1453
1454   /*// TODO: Handling of Program listing for Docbook to be implemented
1455     if (Config_getBool("DOCBOOK_PROGRAMLISTING"))
1456     {
1457     t << "    <programlisting>" << endl;
1458     writeDocbookCodeBlock(t,fd);
1459     t << "    </programlisting>" << endl;
1460     }
1461    */
1462
1463   t << "</section>" << endl;
1464
1465 }
1466
1467 static void generateDocbookForGroup(GroupDef *gd,FTextStream &ti)
1468 {
1469   // + members
1470   // + member groups
1471   // + files
1472   // + classes
1473   // + namespaces
1474   // - packages
1475   // + pages
1476   // + child groups
1477   // - examples
1478   // + brief description
1479   // + detailed description
1480
1481   if (gd->isReference()) return; // skip external references
1482
1483   if (!gd->isASubGroup()) 
1484   {
1485     QCString fileDocbook=gd->getOutputFileBase()+".xml";
1486     //Add the file Documentation info to index file
1487     ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1488   }
1489
1490   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1491   QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml";
1492
1493   QFile f(fileName);
1494   if (!f.open(IO_WriteOnly))
1495   {
1496     err("Cannot open file %s for writing!\n",fileName.data());
1497     return;
1498   }
1499
1500   FTextStream t(&f);
1501   //t.setEncoding(FTextStream::UnicodeUTF8);
1502   writeDocbookHeader_ID(t, gd->getOutputFileBase());
1503
1504   t << "    <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl;
1505
1506   if (gd->briefDescription()) 
1507   {
1508     t << "    <simplesect>" << endl;
1509     t << "        <title>Brief Description</title>" << endl;
1510     writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription());
1511     t << "    </simplesect>" << endl;
1512   }
1513
1514   if (gd->documentation()) 
1515   {
1516     t << "        <simplesect>" << endl;
1517     t << "            <title>Detailed Description</title>" << endl;
1518     writeDocbookDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation());
1519     t << "        </simplesect>" << endl;
1520   }
1521
1522   writeInnerFiles(gd->getFiles(),t);
1523   writeInnerClasses(gd->getClasses(),t);
1524   writeInnerNamespaces(gd->getNamespaces(),t);
1525   writeInnerPages(gd->getPages(),t);
1526   writeInnerGroups(gd->getSubGroups(),t);
1527
1528   if (gd->getMemberGroupSDict())
1529   {
1530     MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
1531     MemberGroup *mg;
1532     for (;(mg=mgli.current());++mgli)
1533     {
1534       generateDocbookSection(gd,t,mg->members(),"user-defined",0,mg->header(),
1535           mg->documentation());
1536     }
1537   }
1538
1539   QListIterator<MemberList> mli(gd->getMemberLists());
1540   MemberList *ml;
1541   for (mli.toFirst();(ml=mli.current());++mli)
1542   {
1543     if ((ml->listType()&MemberListType_declarationLists)!=0)
1544     {
1545       generateDocbookSection(gd,t,ml,g_docbookSectionMapper.find(ml->listType()));
1546     }
1547   }
1548   for (mli.toFirst();(ml=mli.current());++mli)
1549   {
1550     if ((ml->listType()&MemberListType_declarationLists)!=0)
1551     {
1552       generateDocbookSection(gd,t,ml,g_docbookSectionMapper.find(ml->listType()),1);
1553     }
1554   }
1555
1556   writeInnerGroupFiles(gd->getSubGroups(),t);
1557
1558   t << "</section>" << endl;
1559
1560 }
1561
1562 static void generateDocbookForDir(DirDef *dd,FTextStream &ti)
1563 {
1564   if (dd->isReference()) return; // skip external references
1565
1566   QCString fileDocbook=dd->getOutputFileBase()+".xml";
1567   //Add the file Documentation info to index file
1568   ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1569
1570   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1571   QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml";
1572   QFile f(fileName);
1573   if (!f.open(IO_WriteOnly))
1574   {
1575     err("Cannot open file %s for writing!\n",fileName.data());
1576     return;
1577   }
1578
1579   FTextStream t(&f);
1580   //t.setEncoding(FTextStream::UnicodeUTF8);
1581   writeDocbookHeader_ID(t, dd->getOutputFileBase());
1582
1583   t << "    <title>";
1584   writeDocbookString(t, dd->displayName());
1585   t << " Directory Reference";
1586   t << "</title>" << endl;
1587
1588   writeInnerDirs(&dd->subDirs(),t);
1589   writeInnerFiles(dd->getFiles(),t);
1590
1591   t << "    <simplesect>" << endl;
1592   t << "        <title>Detailed Description</title>" << endl;
1593   writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription());
1594   writeDocbookDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation());
1595   t << "    <para>Directory location is " << dd->name() << "</para>" << endl;
1596   t << "    </simplesect>" << endl;
1597
1598   t << "</section>" << endl;
1599 }
1600
1601 static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample)
1602 {
1603   // + name
1604   // + title
1605   // + documentation
1606
1607   if (pd->isReference()) return;
1608
1609   QCString pageName = pd->getOutputFileBase();
1610   if (pd->getGroupDef())
1611   {
1612     pageName+=(QCString)"_"+pd->name();
1613   }
1614   if (pageName=="index") 
1615   {
1616     pageName="mainpage"; // to prevent overwriting the generated index page.
1617   }
1618
1619   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1620   QCString fileName=outputDirectory+"/"+pageName+".xml";
1621   QFile f(fileName);
1622   if (!f.open(IO_WriteOnly))
1623   {
1624     err("Cannot open file %s for writing!\n",fileName.data());
1625     return;
1626   }
1627
1628   FTextStream t(&f);
1629   //t.setEncoding(FTextStream::UnicodeUTF8);
1630
1631   if (!pd->hasParentPage()) 
1632   {
1633     QCString fileDocbook=pageName+".xml";
1634     //Add the file Documentation info to index file
1635     ti << "        <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl;
1636     writeDocbookHeaderMainpage(t);
1637   } 
1638   else 
1639   {
1640     QCString pid = pageName+"_1"+pageName;
1641     writeDocbookHeader_ID(t, pid);
1642   }
1643
1644   SectionInfo *si = Doxygen::sectionDict->find(pd->name());
1645   if (si)
1646   {
1647     t << "    <title>" << convertToXML(si->title) << "</title>" << endl;
1648   } 
1649   else 
1650   {
1651     t << "    <title>" << convertToXML(pd->name()) << "</title>" << endl;
1652   }
1653
1654   if (isExample)
1655   {
1656     writeDocbookDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1657         pd->documentation()+"\n&lt;include "+pd->name()+"&gt;");
1658   }
1659   else
1660   {
1661     writeDocbookDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1662         pd->documentation());
1663   }
1664   writeInnerPages(pd->getSubPages(),t);
1665
1666   if (!pd->hasParentPage()) 
1667   {
1668     t << endl << "</chapter>" << endl;
1669   } 
1670   else 
1671   {
1672     t << endl << "</section>" << endl;
1673   }
1674 }
1675
1676 void generateDocbook()
1677 {
1678
1679   // + classes
1680   // + namespaces
1681   // + files
1682   // + groups
1683   // + related pages
1684   // - examples
1685
1686   QCString outputDirectory = Config_getString("DOCBOOK_OUTPUT");
1687   if (outputDirectory.isEmpty())
1688   {
1689     outputDirectory=QDir::currentDirPath().utf8();
1690   }
1691   else
1692   {
1693     QDir dir(outputDirectory);
1694     if (!dir.exists())
1695     {
1696       dir.setPath(QDir::currentDirPath());
1697       if (!dir.mkdir(outputDirectory))
1698       {
1699         err("tag DOCBOOK_OUTPUT: Output directory `%s' does not "
1700             "exist and cannot be created\n",outputDirectory.data());
1701         exit(1);
1702       }
1703       else
1704       {
1705         msg("Notice: Output directory `%s' does not exist. "
1706             "I have created it for you.\n", outputDirectory.data());
1707       }
1708       dir.cd(outputDirectory);
1709     }
1710     outputDirectory=dir.absPath().utf8();
1711   }
1712
1713   QDir dir(outputDirectory);
1714   if (!dir.exists())
1715   {
1716     dir.setPath(QDir::currentDirPath());
1717     if (!dir.mkdir(outputDirectory))
1718     {
1719       err("Cannot create directory %s\n",outputDirectory.data());
1720       return;
1721     }
1722   }
1723   QDir docbookDir(outputDirectory);
1724   createSubDirs(docbookDir);
1725
1726   QCString fileName=outputDirectory+"/index.xml";
1727   QCString dbk_projectName = Config_getString("PROJECT_NAME");
1728   QFile f(fileName);
1729
1730   f.setName(fileName);
1731   if (!f.open(IO_WriteOnly))
1732   {
1733     err("Cannot open file %s for writing!\n",fileName.data());
1734     return;
1735   }
1736   FTextStream t(&f);
1737   //t.setEncoding(FTextStream::UnicodeUTF8);
1738
1739   // write index header for Docbook which calls the structure file
1740   t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
1741   t << "<book xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
1742   t << "    <info>" << endl;
1743   t << "    <title>" << dbk_projectName << "</title>" << endl;
1744   t << "    </info>" << endl;
1745
1746   // NAMESPACE DOCUMENTATION
1747
1748   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1749   NamespaceDef *nd;
1750
1751   //Namespace Documentation index header
1752   if (nli.toFirst()) 
1753   {
1754     t << "    <chapter>" << endl;
1755     t << "        <title>Namespace Documentation</title>" << endl;
1756   }
1757
1758   for (nli.toFirst();(nd=nli.current());++nli)
1759   {
1760     msg("Generating Docbook output for namespace %s\n",nd->name().data());
1761     generateDocbookForNamespace(nd,t);
1762   }
1763
1764   //Namespace Documentation index footer
1765   if (nli.toFirst()) 
1766   {
1767     t << "    </chapter>" << endl;
1768   }
1769
1770   /** MAINPAGE DOCUMENTATION **/
1771
1772   if (Doxygen::mainPage)
1773   {
1774     msg("Generating Docbook output for the main page\n");
1775     generateDocbookForPage(Doxygen::mainPage,t,FALSE);
1776   }
1777
1778   // PAGE DOCUMENTATION
1779   {
1780     PageSDict::Iterator pdi(*Doxygen::pageSDict);
1781     PageDef *pd=0;
1782
1783     for (pdi.toFirst();(pd=pdi.current());++pdi)
1784     {
1785       msg("Generating Docbook output for page %s\n",pd->name().data());
1786       generateDocbookForPage(pd,t,FALSE);
1787     }
1788   }
1789
1790   /** MODULE GROUP DOCUMENTATION **/
1791
1792   GroupSDict::Iterator gli(*Doxygen::groupSDict);
1793   GroupDef *gd;
1794
1795   //Module group Documentation index header
1796   if (gli.toFirst()) 
1797   {
1798     t << "    <chapter>" << endl;
1799     t << "        <title>Module Documentation</title>" << endl;
1800   }
1801
1802   for (;(gd=gli.current());++gli)
1803   {
1804     msg("Generating Docbook output for group %s\n",gd->name().data());
1805     generateDocbookForGroup(gd,t);
1806   }
1807
1808   //Module group Documentation index footer
1809   if (gli.toFirst()) 
1810   {
1811     t << "    </chapter>" << endl;
1812   }
1813
1814   //CLASS DOCUMENTATION
1815
1816   {
1817     ClassSDict::Iterator cli(*Doxygen::classSDict);
1818     ClassDef *cd;
1819
1820     //Class Documentation index header
1821     if (cli.toFirst()) 
1822     {
1823       t << "    <chapter>" << endl;
1824       t << "        <title>Class Documentation</title>" << endl;
1825     }
1826
1827     for (cli.toFirst();(cd=cli.current());++cli)
1828     {
1829       generateDocbookForClass(cd,t);
1830     }
1831
1832     //Class Documentation index footer
1833     if (cli.toFirst()) 
1834     {
1835       t << "    </chapter>" << endl;
1836     }
1837   }
1838
1839   // FILE DOCUMENTATION
1840
1841   FileNameListIterator fnli(*Doxygen::inputNameList);
1842   FileName *fn;
1843
1844   //File Documentation index header
1845   if (fnli.toFirst()) 
1846   {
1847     t << "    <chapter>" << endl;
1848     t << "        <title>File Documentation</title>" << endl;
1849   }
1850
1851   for (;(fn=fnli.current());++fnli)
1852   {
1853     FileNameIterator fni(*fn);
1854     FileDef *fd;
1855     for (;(fd=fni.current());++fni)
1856     {
1857       msg("Generating Docbook output for file %s\n",fd->name().data());
1858       generateDocbookForFile(fd,t);
1859     }
1860   }
1861
1862   //File Documentation index footer
1863   if (fnli.toFirst()) 
1864   {
1865     t << "    </chapter>" << endl;
1866   }
1867
1868   // DIRECTORY DOCUMENTATION
1869
1870   {
1871     DirDef *dir;
1872     DirSDict::Iterator sdi(*Doxygen::directories);
1873
1874     //Directory Documentation index header
1875     if (sdi.toFirst()) 
1876     {
1877       t << "    <chapter>" << endl;
1878       t << "        <title>Directory Documentation</title>" << endl;
1879     }
1880
1881     for (sdi.toFirst();(dir=sdi.current());++sdi)
1882     {
1883       msg("Generate Docbook output for dir %s\n",dir->name().data());
1884       generateDocbookForDir(dir,t);
1885     }
1886
1887     //Module group Documentation index footer
1888     if (sdi.toFirst()) 
1889     {
1890       t << "    </chapter>" << endl;
1891     }
1892   }
1893
1894   // EXAMPLE PAGE DOCUMENTATION
1895
1896   {
1897     PageSDict::Iterator pdi(*Doxygen::exampleSDict);
1898     PageDef *pd=0;
1899
1900     //Example Page Documentation index header
1901     if (pdi.toFirst()) 
1902     {
1903       t << "    <chapter>" << endl;
1904       t << "        <title>Example Documentation</title>" << endl;
1905     }
1906
1907     for (pdi.toFirst();(pd=pdi.current());++pdi)
1908     {
1909       msg("Generating Docbook output for example %s\n",pd->name().data());
1910       generateDocbookForPage(pd,t,TRUE);
1911     }
1912
1913     //Example Page Documentation index footer
1914     if (pdi.toFirst()) 
1915     {
1916       t << "    </chapter>" << endl;
1917     }
1918   }
1919
1920   t << "</book>" << endl;
1921
1922 }
1923
1924