Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / context.cpp
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15
16 #include <assert.h>
17 #include <qdir.h>
18
19 #include "context.h"
20 #include "config.h"
21 #include "index.h"
22 #include "classlist.h"
23 #include "doxygen.h"
24 #include "namespacedef.h"
25 #include "filedef.h"
26 #include "pagedef.h"
27 #include "groupdef.h"
28 #include "util.h"
29 #include "version.h"
30 #include "language.h"
31 #include "message.h"
32 #include "vhdldocgen.h"
33 #include "filename.h"
34 #include "dirdef.h"
35 #include "docparser.h"
36 #include "htmlgen.h"
37 #include "htmldocvisitor.h"
38 #include "htmlhelp.h"
39 #include "latexgen.h"
40 #include "latexdocvisitor.h"
41 #include "dot.h"
42 #include "diagram.h"
43 #include "example.h"
44 #include "membername.h"
45 #include "parserintf.h"
46 #include "portable.h"
47 #include "arguments.h"
48 #include "groupdef.h"
49 #include "searchindex.h"
50 #include "resourcemgr.h"
51
52 // TODO: pass the current file to Dot*::writeGraph, so the user can put dot graphs in other
53 //       files as well
54
55 enum ContextOutputFormat
56 {
57   ContextOutputFormat_Unspecified=0,
58   ContextOutputFormat_Html,
59   ContextOutputFormat_Latex,
60   ContextOutputFormat_Rtf,
61   ContextOutputFormat_ManPage,
62   ContextOutputFormat_DocBook,
63   ContextOutputFormat_Xml,
64   ContextOutputFormat_TagFile
65 };
66
67 struct ContextGlobals
68 {
69   int                 dynSectionId;
70   QCString            outputDir;
71   ContextOutputFormat outputFormat;
72 } g_globals;
73
74 /** @brief Scoped smart pointer */
75 template<class T> class ScopedPtr
76 {
77   private:
78     T *m_ptr;
79     ScopedPtr(const ScopedPtr &);
80     ScopedPtr &operator=(const ScopedPtr &);
81     void operator==(const ScopedPtr &) const;
82     void operator!=(const ScopedPtr &) const;
83
84   public:
85     typedef T Type;
86     explicit ScopedPtr(T *p=0) : m_ptr(p) {}
87     ~ScopedPtr() { delete m_ptr; };
88     T &operator*() const { return *m_ptr; }
89     T *operator->() const { return m_ptr; }
90     T *get() const { return m_ptr; }
91     operator bool() const { return m_ptr!=0; }
92     void reset(T *p=0) { if (p!=m_ptr) { delete m_ptr; m_ptr = p; } }
93 };
94
95 /** @brief Reference counting smart pointer */
96 template<class T> class SharedPtr
97 {
98   private:
99     T *m_ptr;
100     SharedPtr(const SharedPtr &);
101     SharedPtr &operator=(const SharedPtr &p);
102     void operator==(const SharedPtr &) const;
103     void operator!=(const SharedPtr &) const;
104
105   public:
106     typedef T Type;
107     explicit SharedPtr(T *p=0) : m_ptr(p) { if (m_ptr) m_ptr->addRef(); }
108     ~SharedPtr() { if (m_ptr) m_ptr->release(); };
109     T &operator*() const { return *m_ptr; }
110     T *operator->() const { return m_ptr; }
111     T *get() const { return m_ptr; }
112     operator bool() const { return m_ptr!=0; }
113     void reset(T *p=0)
114     {
115       if (p) p->addRef();
116       if (m_ptr) m_ptr->release();
117       m_ptr = p;
118     }
119 };
120
121 /** @brief Template List iterator support */
122 class GenericConstIterator : public TemplateListIntf::ConstIterator
123 {
124   public:
125     GenericConstIterator(const QList<TemplateVariant> &list)
126       : m_it(list) { }
127     virtual ~GenericConstIterator() {}
128     void toFirst()
129     {
130       m_it.toFirst();
131     }
132     void toLast()
133     {
134       m_it.toLast();
135     }
136     void toNext()
137     {
138       if (m_it.current()) ++m_it;
139     }
140     void toPrev()
141     {
142       if (m_it.current()) --m_it;
143     }
144     bool current(TemplateVariant &v) const
145     {
146       if (m_it.current())
147       {
148         v = *m_it.current();
149         return TRUE;
150       }
151       else
152       {
153         v = TemplateVariant();
154         return FALSE;
155       }
156     }
157   private:
158     QListIterator<TemplateVariant> m_it;
159 };
160
161 //------------------------------------------------------------------------
162
163 /** @brief standard template list implementation */
164 class GenericNodeListContext : public TemplateListIntf
165 {
166   public:
167     GenericNodeListContext() : m_refCount(0)
168     {
169       m_children.setAutoDelete(TRUE);
170     }
171     static GenericNodeListContext *alloc()
172     {
173       return new GenericNodeListContext;
174     }
175
176     // TemplateListIntf methods
177     int count() const
178     {
179       return (int)m_children.count();
180     }
181     TemplateVariant at(int index) const
182     {
183       TemplateVariant result;
184       if (index>=0 && index<count())
185       {
186         result = *m_children.at(index);
187       }
188       return result;
189     }
190     TemplateListIntf::ConstIterator *createIterator() const
191     {
192       return new GenericConstIterator(m_children);
193     }
194
195     void append(const TemplateVariant &ctn)
196     {
197       m_children.append(new TemplateVariant(ctn));
198     }
199     bool isEmpty() const
200     {
201       return m_children.isEmpty();
202     }
203     int addRef()
204     {
205       return ++m_refCount;
206     }
207     int release()
208     {
209       int count = --m_refCount;
210       if (count<=0)
211       {
212         delete this;
213       }
214       return count;
215     }
216   private:
217     mutable QList<TemplateVariant> m_children;
218     int m_refCount;
219 };
220
221 //------------------------------------------------------------------------
222
223 /** @brief Helper class to map a property name to a handler member function */
224 template<typename T>
225 class PropertyMapper
226 {
227   private:
228     struct PropertyFuncIntf
229     {
230       virtual ~PropertyFuncIntf() {}
231       virtual TemplateVariant operator()(const T *obj) const = 0;
232     };
233     struct PropertyFunc : public PropertyFuncIntf
234     {
235       typedef TemplateVariant (T::*Handler)() const;
236       PropertyFunc(Handler h) : handler(h) {}
237       TemplateVariant operator()(const T *obj) const
238       {
239         return (obj->*handler)();
240       }
241       Handler handler;
242     };
243
244   public:
245     PropertyMapper() : m_map(63) { m_map.setAutoDelete(TRUE); }
246
247     /** Add a property to the map
248      *  @param[in] name   The name of the property to add.
249      *  @param[in] handle The method to call when the property is accessed.
250      */
251     void addProperty(const char *name,typename PropertyFunc::Handler handle)
252     {
253       if (m_map.find(name))
254       {
255         err("Error: adding property '%s' more than once",name);
256       }
257       else
258       {
259         m_map.insert(name,new PropertyFunc(handle));
260       }
261     }
262
263     /** Gets the value of a property.
264      *  @param[in] obj  The object handling access to the property.
265      *  @param[in] name The name of the property.
266      *  @returns A variant representing the properties value or an
267      *  invalid variant if it was not found.
268      */
269     TemplateVariant get(const T *obj,const char *name) const
270     {
271       //printf("PropertyMapper::get(%s)\n",name);
272       TemplateVariant result;
273       PropertyFuncIntf *func = m_map.find(name);
274       if (func)
275       {
276         result = (*func)(obj);
277       }
278       return result;
279     }
280
281   private:
282     QDict<PropertyFuncIntf> m_map;
283 };
284
285
286 //------------------------------------------------------------------------
287
288 //%% struct Config : configuration options
289 //%% {
290 class ConfigContext::Private
291 {
292   public:
293     Private() { m_cachedLists.setAutoDelete(TRUE); }
294     virtual ~Private() { }
295     TemplateVariant fetchList(const QCString &name,const QStrList *list)
296     {
297       TemplateVariant *v = m_cachedLists.find(name);
298       if (v==0)
299       {
300         TemplateList *tlist = TemplateList::alloc();
301         m_cachedLists.insert(name,new TemplateVariant(tlist));
302         QStrListIterator li(*list);
303         char *s;
304         for (li.toFirst();(s=li.current());++li)
305         {
306           tlist->append(s);
307         }
308         return tlist;
309       }
310       else
311       {
312         return *v;
313       }
314     }
315   private:
316     QDict<TemplateVariant> m_cachedLists;
317 };
318 //%% }
319
320 ConfigContext::ConfigContext() : RefCountedContext("ConfigContext")
321 {
322   p = new Private;
323 }
324
325 ConfigContext::~ConfigContext()
326 {
327   delete p;
328 }
329
330 TemplateVariant ConfigContext::get(const char *name) const
331 {
332   TemplateVariant result;
333   if (name)
334   {
335     const ConfigValues::Info *option = ConfigValues::instance().get(name);
336     if (option)
337     {
338       switch (option->type)
339       {
340         case ConfigValues::Info::Bool:
341           {
342             bool b = ConfigValues::instance().*((ConfigValues::InfoBool*)option)->item;
343             return TemplateVariant(b);
344           }
345         case ConfigValues::Info::Int:
346           {
347             int i = ConfigValues::instance().*((ConfigValues::InfoInt*)option)->item;
348             return TemplateVariant(i);
349           }
350         case ConfigValues::Info::String:
351           {
352             QCString s = ConfigValues::instance().*((ConfigValues::InfoString*)option)->item;
353             return TemplateVariant(s);
354           }
355         case ConfigValues::Info::List:
356           {
357             const QStrList &l = ConfigValues::instance().*((ConfigValues::InfoList*)option)->item;
358             return p->fetchList(name,&l);
359           }
360         default:
361           break;
362       }
363     }
364   }
365   return result;
366 }
367
368 //------------------------------------------------------------------------
369
370 //%% struct Doxygen: global information
371 //%% {
372 class DoxygenContext::Private
373 {
374   public:
375     TemplateVariant version() const
376     {
377       return versionString;
378     }
379     TemplateVariant date() const
380     {
381       return dateToString(TRUE);
382     }
383     TemplateVariant maxJaxCodeFile() const
384     {
385       return m_cache.maxJaxCodeFile;
386     }
387     Private()
388     {
389       static bool init=FALSE;
390       if (!init)
391       {
392         //%% string version
393         s_inst.addProperty("version",         &Private::version);
394         //%% string date
395         s_inst.addProperty("date",            &Private::date);
396         //%% string maxJaxCodeFile
397         s_inst.addProperty("mathJaxCodeFile", &Private::maxJaxCodeFile);
398         init=TRUE;
399       }
400     }
401     TemplateVariant get(const char *n) const
402     {
403       return s_inst.get(this,n);
404     }
405   private:
406     struct Cachable
407     {
408       Cachable() { maxJaxCodeFile=fileToString(Config_getString(MATHJAX_CODEFILE)); }
409       QCString maxJaxCodeFile;
410     };
411     mutable Cachable m_cache;
412     static PropertyMapper<DoxygenContext::Private> s_inst;
413 };
414 //%% }
415
416 PropertyMapper<DoxygenContext::Private> DoxygenContext::Private::s_inst;
417 //                                (PropertyMapper<DoxygenContext::Private>::instance());
418
419 DoxygenContext::DoxygenContext() : RefCountedContext("DoxygenContext")
420 {
421   p = new Private;
422 }
423
424 DoxygenContext::~DoxygenContext()
425 {
426   delete p;
427 }
428
429 TemplateVariant DoxygenContext::get(const char *n) const
430 {
431   return p->get(n);
432 }
433
434 //------------------------------------------------------------------------
435
436 //%% struct Translator: translation methods
437 //%% {
438 class TranslateContext::Private
439 {
440   public:
441
442     TemplateVariant handleGeneratedAt(const QValueList<TemplateVariant> &args) const
443     {
444       if (args.count()==2)
445       {
446         return theTranslator->trGeneratedAt(args[0].toString(),args[1].toString());
447       }
448       else
449       {
450         err("tr.generateAt should take two arguments, got %d!\n",args.count());
451       }
452       return TemplateVariant();
453     }
454     TemplateVariant handleInheritanceDiagramFor(const QValueList<TemplateVariant> &args) const
455     {
456       if (args.count()==1)
457       {
458         return theTranslator->trClassDiagram(args[0].toString());
459       }
460       else
461       {
462         err("tr.inheritanceDiagramFor should take one argument, got %d!\n",args.count());
463       }
464       return TemplateVariant();
465     }
466     TemplateVariant handleCollaborationDiagramFor(const QValueList<TemplateVariant> &args) const
467     {
468       if (args.count()==1)
469       {
470         return theTranslator->trCollaborationDiagram(args[0].toString());
471       }
472       else
473       {
474         err("tr.collaborationDiagramFor should take one argument, got %d!\n",args.count());
475       }
476       return TemplateVariant();
477     }
478     TemplateVariant handleDirDependencyGraphFor(const QValueList<TemplateVariant> &args) const
479     {
480       if (args.count()==1)
481       {
482         return theTranslator->trDirDepGraph(args[0].toString());
483       }
484       else
485       {
486         err("tr.dirDependencyGraphFor should take one argument, got %d!\n",args.count());
487       }
488       return TemplateVariant();
489     }
490     TemplateVariant handleInheritsList(const QValueList<TemplateVariant> &args) const
491     {
492       if (args.count()==1)
493       {
494         return theTranslator->trInheritsList(args[0].toInt());
495       }
496       else
497       {
498         err("tr.inheritsList should take one integer argument, got %d!\n",args.count());
499       }
500       return TemplateVariant();
501     }
502     TemplateVariant handleInheritedByList(const QValueList<TemplateVariant> &args) const
503     {
504       if (args.count()==1)
505       {
506         return theTranslator->trInheritedByList(args[0].toInt());
507       }
508       else
509       {
510         err("tr.inheritedByList should take one integer argument, got %d!\n",args.count());
511       }
512       return TemplateVariant();
513     }
514     TemplateVariant handleWriteList(const QValueList<TemplateVariant> &args) const
515     {
516       if (args.count()==1)
517       {
518         return theTranslator->trWriteList(args[0].toInt());
519       }
520       else
521       {
522         err("tr.*List should take one integer argument, got %d!\n",args.count());
523       }
524       return TemplateVariant();
525     }
526     TemplateVariant handleImplementedBy(const QValueList<TemplateVariant> &args) const
527     {
528       if (args.count()==1)
529       {
530         return theTranslator->trImplementedInList(args[0].toInt());
531       }
532       else
533       {
534         err("tr.implementedBy should take one integer argument, got %d!\n",args.count());
535       }
536       return TemplateVariant();
537     }
538     TemplateVariant handleReimplementedBy(const QValueList<TemplateVariant> &args) const
539     {
540       if (args.count()==1)
541       {
542         return theTranslator->trReimplementedInList(args[0].toInt());
543       }
544       else
545       {
546         err("tr.reimplementedBy should take one integer argument, got %d!\n",args.count());
547       }
548       return TemplateVariant();
549     }
550     TemplateVariant handleSourceRefs(const QValueList<TemplateVariant> &args) const
551     {
552       if (args.count()==1)
553       {
554         return theTranslator->trReferences()+" "+theTranslator->trWriteList(args[0].toInt())+".";
555       }
556       else
557       {
558         err("tr.sourceRefs should take one integer argument, got %d\n",args.count());
559       }
560       return TemplateVariant();
561     }
562     TemplateVariant handleSourceRefBys(const QValueList<TemplateVariant> &args) const
563     {
564       if (args.count()==1)
565       {
566         return theTranslator->trReferencedBy()+" "+theTranslator->trWriteList(args[0].toInt())+".";
567       }
568       else
569       {
570         err("tr.sourceRefBys should take one integer argument, got %d\n",args.count());
571       }
572       return TemplateVariant();
573     }
574     TemplateVariant handleIncludeDependencyGraph(const QValueList<TemplateVariant> &args) const
575     {
576       if (args.count()==1)
577       {
578         return theTranslator->trInclDepGraph(args[0].toString());
579       }
580       else
581       {
582         err("tr.includeDependencyGraph should take one string argument, got %d\n",args.count());
583       }
584       return TemplateVariant();
585     }
586
587
588
589     TemplateVariant generatedBy() const
590     {
591       return theTranslator->trGeneratedBy();
592     }
593     TemplateVariant generatedAt() const
594     {
595       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleGeneratedAt>(this);
596     }
597     TemplateVariant inheritanceDiagramFor() const
598     {
599       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleInheritanceDiagramFor>(this);
600     }
601     TemplateVariant collaborationDiagramFor() const
602     {
603       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleCollaborationDiagramFor>(this);
604     }
605     TemplateVariant dirDependencyGraphFor() const
606     {
607       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleDirDependencyGraphFor>(this);
608     }
609     TemplateVariant search() const
610     {
611       return theTranslator->trSearch();
612     }
613     TemplateVariant mainPage() const
614     {
615       return theTranslator->trMainPage();
616     }
617     TemplateVariant classes() const
618     {
619       return theTranslator->trClasses();
620       // TODO: VHDL: theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE)
621       // TODO: Fortran: trDataTypes()
622     }
623     TemplateVariant classList() const
624     {
625       return theTranslator->trCompoundList();
626     }
627     TemplateVariant classListDescription() const
628     {
629       return theTranslator->trCompoundListDescription();
630     }
631     TemplateVariant classIndex() const
632     {
633       return theTranslator->trCompoundIndex();
634     }
635     TemplateVariant namespaceIndex() const
636     {
637       return theTranslator->trNamespaceIndex();
638     }
639     TemplateVariant classHierarchy() const
640     {
641       return theTranslator->trClassHierarchy();
642     }
643     TemplateVariant classMembers() const
644     {
645       return theTranslator->trCompoundMembers();
646     }
647     TemplateVariant modules() const
648     {
649       return theTranslator->trModules();
650     }
651     TemplateVariant moduleIndex() const
652     {
653       return theTranslator->trModuleIndex();
654     }
655     TemplateVariant namespaces() const
656     {
657       if (m_javaOpt || m_vhdlOpt)
658       {
659         return theTranslator->trPackages();
660       }
661       else if (m_fortranOpt || m_sliceOpt)
662       {
663         return theTranslator->trModules();
664       }
665       else
666       {
667         return theTranslator->trNamespaces();
668       }
669     }
670     TemplateVariant files() const
671     {
672       return theTranslator->trFile(TRUE,FALSE);
673     }
674     TemplateVariant fileIndex() const
675     {
676       return theTranslator->trFileIndex();
677     }
678     TemplateVariant pages() const
679     {
680       return theTranslator->trRelatedPages();
681     }
682     TemplateVariant examples() const
683     {
684       return theTranslator->trExamples();
685     }
686     TemplateVariant namespaceList() const
687     {
688       if (m_javaOpt || m_vhdlOpt)
689       {
690         return theTranslator->trPackages();
691       }
692       else if (m_fortranOpt || m_sliceOpt)
693       {
694         return theTranslator->trModulesList();
695       }
696       else
697       {
698         return theTranslator->trNamespaceList();
699       }
700     }
701     TemplateVariant namespaceMembers() const
702     {
703       if (m_javaOpt || m_vhdlOpt)
704       {
705         return theTranslator->trPackageMembers();
706       }
707       else if (m_fortranOpt || m_sliceOpt)
708       {
709         return theTranslator->trModulesMembers();
710       }
711       else
712       {
713         return theTranslator->trNamespaceMembers();
714       }
715     }
716     TemplateVariant moduleDocumentation() const
717     {
718       return theTranslator->trModuleDocumentation();
719     }
720     TemplateVariant fileDocumentation() const
721     {
722       return theTranslator->trFileDocumentation();
723     }
724     TemplateVariant fileList() const
725     {
726       return theTranslator->trFileList();
727     }
728     TemplateVariant fileMembers() const
729     {
730       return theTranslator->trFileMembers();
731     }
732     TemplateVariant fileMembersDescription() const
733     {
734       static bool extractAll = Config_getBool(EXTRACT_ALL);
735       return theTranslator->trFileMembersDescription(extractAll);
736     }
737     TemplateVariant namespaceMembersDescription() const
738     {
739       static bool extractAll = Config_getBool(EXTRACT_ALL);
740       return theTranslator->trNamespaceMemberDescription(extractAll);
741     }
742     TemplateVariant classHierarchyDescription() const
743     {
744       return theTranslator->trClassHierarchyDescription();
745     }
746     TemplateVariant gotoGraphicalHierarchy() const
747     {
748       return theTranslator->trGotoGraphicalHierarchy();
749     }
750     TemplateVariant gotoTextualHierarchy() const
751     {
752       return theTranslator->trGotoTextualHierarchy();
753     }
754     TemplateVariant classMembersDescription() const
755     {
756       static bool extractAll = Config_getBool(EXTRACT_ALL);
757       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
758       if (fortranOpt)
759       {
760         return theTranslator->trCompoundMembersDescriptionFortran(extractAll);
761       }
762       else
763       {
764         return theTranslator->trCompoundMembersDescription(extractAll);
765       }
766     }
767     TemplateVariant relatedPagesDesc() const
768     {
769       return theTranslator->trRelatedPagesDescription();
770     }
771     TemplateVariant more() const
772     {
773       return theTranslator->trMore();
774     }
775     TemplateVariant detailedDesc() const
776     {
777       return theTranslator->trDetailedDescription();
778     }
779     TemplateVariant inheritsList() const
780     {
781       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleInheritsList>(this);
782     }
783     TemplateVariant inheritedByList() const
784     {
785       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleInheritedByList>(this);
786     }
787     TemplateVariant definedAtLineInSourceFile() const
788     {
789       return theTranslator->trDefinedAtLineInSourceFile();
790     }
791     TemplateVariant typeConstraints() const
792     {
793       return theTranslator->trTypeConstraints();
794     }
795     TemplateVariant exampleList() const
796     {
797       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleWriteList>(this);
798     }
799     TemplateVariant listOfAllMembers() const
800     {
801       return theTranslator->trListOfAllMembers();
802     }
803     TemplateVariant memberList() const
804     {
805       return theTranslator->trMemberList();
806     }
807     TemplateVariant theListOfAllMembers() const
808     {
809       return theTranslator->trThisIsTheListOfAllMembers();
810     }
811     TemplateVariant incInheritedMembers() const
812     {
813       return theTranslator->trIncludingInheritedMembers();
814     }
815     TemplateVariant defineValue() const
816     {
817       return theTranslator->trDefineValue();
818     }
819     TemplateVariant initialValue() const
820     {
821       return theTranslator->trInitialValue();
822     }
823     TemplateVariant enumerationValues() const
824     {
825       return theTranslator->trEnumerationValues();
826     }
827     TemplateVariant implements() const
828     {
829       return theTranslator->trImplementedFromList(1);
830     }
831     TemplateVariant reimplements() const
832     {
833       return theTranslator->trReimplementedFromList(1);
834     }
835     TemplateVariant implementedBy() const
836     {
837       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleImplementedBy>(this);
838     }
839     TemplateVariant reimplementedBy() const
840     {
841       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleReimplementedBy>(this);
842     }
843     TemplateVariant sourceRefs() const
844     {
845       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleSourceRefs>(this);
846     }
847     TemplateVariant sourceRefBys() const
848     {
849       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleSourceRefBys>(this);
850     }
851     TemplateVariant callGraph() const
852     {
853       return theTranslator->trCallGraph();
854     }
855     TemplateVariant callerGraph() const
856     {
857       return theTranslator->trCallerGraph();
858     }
859     TemplateVariant referencedByRelation() const
860     {
861       return theTranslator->trReferencedBy();
862     }
863     TemplateVariant referencesRelation() const
864     {
865       return theTranslator->trReferences();
866     }
867     TemplateVariant inheritedFrom() const
868     {
869       return theTranslator->trInheritedFrom("@0","@1");
870     }
871     TemplateVariant additionalInheritedMembers() const
872     {
873       return theTranslator->trAdditionalInheritedMembers();
874     }
875     TemplateVariant includeDependencyGraph() const
876     {
877       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleIncludeDependencyGraph>(this);
878     }
879     TemplateVariant includedByDependencyGraph() const
880     {
881       return theTranslator->trInclByDepGraph();
882     }
883     TemplateVariant gotoSourceCode() const
884     {
885       return theTranslator->trGotoSourceCode();
886     }
887     TemplateVariant gotoDocumentation() const
888     {
889       return theTranslator->trGotoDocumentation();
890     }
891     TemplateVariant constantgroups() const
892     {
893       return theTranslator->trConstantGroups();
894     }
895     TemplateVariant classDocumentation() const
896     {
897       return theTranslator->trClassDocumentation();
898     }
899     TemplateVariant namespaceDocumentation() const
900     {
901       return theTranslator->trNamespaceDocumentation();
902     }
903     TemplateVariant compoundMembers() const
904     {
905       return theTranslator->trCompoundMembers();
906     }
907     TemplateVariant detailLevel() const
908     {
909       return theTranslator->trDetailLevel();
910     }
911     TemplateVariant fileListDescription() const
912     {
913       bool extractAll = Config_getBool(EXTRACT_ALL);
914       return theTranslator->trFileListDescription(extractAll);
915     }
916     TemplateVariant modulesDescription() const
917     {
918       bool extractAll = Config_getBool(EXTRACT_ALL);
919       return theTranslator->trModulesListDescription(extractAll);
920     }
921     TemplateVariant namespaceListDescription() const
922     {
923       bool extractAll = Config_getBool(EXTRACT_ALL);
924       return theTranslator->trNamespaceListDescription(extractAll);
925     }
926     TemplateVariant directories() const
927     {
928       return theTranslator->trDirectories();
929     }
930     TemplateVariant all() const
931     {
932       return theTranslator->trAll();
933     }
934     TemplateVariant functions() const
935     {
936       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
937       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
938       return fortranOpt ? theTranslator->trSubprograms()     :
939              vhdlOpt    ? theTranslator->trFunctionAndProc() :
940                           theTranslator->trFunctions();
941     }
942     TemplateVariant variables() const
943     {
944       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
945       return sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables();
946     }
947     TemplateVariant typedefs() const
948     {
949       return theTranslator->trTypedefs();
950     }
951     TemplateVariant enums() const
952     {
953       return theTranslator->trEnumerations();
954     }
955     TemplateVariant properties() const
956     {
957       return theTranslator->trProperties();
958     }
959     TemplateVariant events() const
960     {
961       return theTranslator->trEvents();
962     }
963     TemplateVariant related() const
964     {
965       return theTranslator->trRelatedFunctions();
966     }
967     TemplateVariant macros() const
968     {
969       return theTranslator->trDefines();
970     }
971     TemplateVariant loading() const
972     {
973       return theTranslator->trLoading();
974     }
975     TemplateVariant searching() const
976     {
977       return theTranslator->trSearching();
978     }
979     TemplateVariant noMatches() const
980     {
981       return theTranslator->trNoMatches();
982     }
983     TemplateVariant enumName() const
984     {
985       return theTranslator->trEnumName();
986     }
987     TemplateVariant enumValue() const
988     {
989       return theTranslator->trEnumValue();
990     }
991     TemplateVariant referenceManual() const
992     {
993       return theTranslator->trReferenceManual();
994     }
995     TemplateVariant index() const
996     {
997       return theTranslator->trRTFGeneralIndex();
998     }
999     TemplateVariant panelSyncOn() const
1000     {
1001       return theTranslator->trPanelSynchronisationTooltip(FALSE);
1002     }
1003     TemplateVariant panelSyncOff() const
1004     {
1005       return theTranslator->trPanelSynchronisationTooltip(TRUE);
1006     }
1007     TemplateVariant providedByCategory() const
1008     {
1009       return theTranslator->trProvidedByCategory();
1010     }
1011     TemplateVariant extendsClass() const
1012     {
1013       return theTranslator->trExtendsClass();
1014     }
1015     TemplateVariant examplesDescription() const
1016     {
1017       return theTranslator->trExamplesDescription();
1018     }
1019     TemplateVariant langString() const
1020     {
1021       return HtmlHelp::getLanguageString();
1022     }
1023     Private()
1024     {
1025       static bool init=FALSE;
1026       if (!init)
1027       {
1028         //%% string generatedBy
1029         s_inst.addProperty("generatedBy",       &Private::generatedBy);
1030         //%% string generatedAt
1031         s_inst.addProperty("generatedAt",       &Private::generatedAt);
1032         //%% string search
1033         s_inst.addProperty("search",            &Private::search);
1034         //%% string mainPage
1035         s_inst.addProperty("mainPage",          &Private::mainPage);
1036         //%% string classes
1037         s_inst.addProperty("classes",           &Private::classes);
1038         //%% string classList
1039         s_inst.addProperty("classList",         &Private::classList);
1040         //%% string classListDescription
1041         s_inst.addProperty("classListDescription", &Private::classListDescription);
1042         //%% string classIndex
1043         s_inst.addProperty("classIndex",        &Private::classIndex);
1044         //%% string namespaceIndex
1045         s_inst.addProperty("namespaceIndex",    &Private::namespaceIndex);
1046         //%% string classHierarchy
1047         s_inst.addProperty("classHierarchy",    &Private::classHierarchy);
1048         //%% string classMembers
1049         s_inst.addProperty("classMembers",      &Private::classMembers);
1050         //%% string classMembersDescription
1051         s_inst.addProperty("classMembersDescription",&Private::classMembersDescription);
1052         //%% string modules
1053         s_inst.addProperty("modules",           &Private::modules);
1054         //%% string moduleIndex
1055         s_inst.addProperty("moduleIndex",       &Private::moduleIndex);
1056         //%% string namespaces
1057         s_inst.addProperty("namespaces",        &Private::namespaces);
1058         //%% string fileIndex
1059         s_inst.addProperty("fileIndex",         &Private::fileIndex);
1060         //%% string files
1061         s_inst.addProperty("files",             &Private::files);
1062         //%% string pages
1063         s_inst.addProperty("pages",             &Private::pages);
1064         //%% string examples
1065         s_inst.addProperty("examples",          &Private::examples);
1066         //%% string namespaceList
1067         s_inst.addProperty("namespaceList",     &Private::namespaceList);
1068         //%% string namespaceMembers
1069         s_inst.addProperty("namespaceMembers",  &Private::namespaceMembers);
1070         //%% srting fileList
1071         s_inst.addProperty("fileList",          &Private::fileList);
1072         //%% string fileMembers
1073         s_inst.addProperty("fileMembers",       &Private::fileMembers);
1074         //%% string fileMembersDescription
1075         s_inst.addProperty("fileMembersDescription", &Private::fileMembersDescription);
1076         //%% string relatedPagesDescripiton
1077         s_inst.addProperty("relatedPagesDesc",  &Private::relatedPagesDesc);
1078         //%% string more
1079         s_inst.addProperty("more",              &Private::more);
1080         //%% string detailedDescription
1081         s_inst.addProperty("detailedDesc",      &Private::detailedDesc);
1082         //%% string inheritanceDiagramFor
1083         s_inst.addProperty("inheritanceDiagramFor", &Private::inheritanceDiagramFor);
1084         //%% string collaborationDiagramFor
1085         s_inst.addProperty("collaborationDiagramFor", &Private::collaborationDiagramFor);
1086         //%% markerstring inheritsList
1087         s_inst.addProperty("inheritsList",      &Private::inheritsList);
1088         //%% markerstring inheritedByList
1089         s_inst.addProperty("inheritedByList",   &Private::inheritedByList);
1090         //%% markerstring definedAtLineInSourceFile
1091         s_inst.addProperty("definedAtLineInSourceFile", &Private::definedAtLineInSourceFile);
1092         //%% string typeConstraints
1093         s_inst.addProperty("typeConstraints",   &Private::typeConstraints);
1094         //%% string exampleList
1095         s_inst.addProperty("exampleList",       &Private::exampleList);
1096         //%% string listOfAllMembers
1097         s_inst.addProperty("listOfAllMembers",  &Private::listOfAllMembers);
1098         //%% string memberList
1099         s_inst.addProperty("memberList",        &Private::memberList);
1100         //%% string theListOfAllMembers
1101         s_inst.addProperty("theListOfAllMembers",&Private::theListOfAllMembers);
1102         //%% string incInheritedMembers
1103         s_inst.addProperty("incInheritedMembers",&Private::incInheritedMembers);
1104         //%% string defineValue
1105         s_inst.addProperty("defineValue",        &Private::defineValue);
1106         //%% string initialValue
1107         s_inst.addProperty("initialValue",       &Private::initialValue);
1108         //%% markerstring implements
1109         s_inst.addProperty("implements",         &Private::implements);
1110         //%% markerstring reimplements
1111         s_inst.addProperty("reimplements",       &Private::reimplements);
1112         //%% markerstring implementedBy
1113         s_inst.addProperty("implementedBy",      &Private::implementedBy);
1114         //%% markerstring reimplementedBy
1115         s_inst.addProperty("reimplementedBy",    &Private::reimplementedBy);
1116         //%% markerstring sourceRefs
1117         s_inst.addProperty("sourceRefs",         &Private::sourceRefs);
1118         //%% markerstring sourceRefBys
1119         s_inst.addProperty("sourceRefBys",       &Private::sourceRefBys);
1120         //%% string callGraph
1121         s_inst.addProperty("callGraph",          &Private::callGraph);
1122         //%% string callerGraph
1123         s_inst.addProperty("callerGraph",        &Private::callerGraph);
1124         //%% string referencedByRelation
1125         s_inst.addProperty("referencedByRelation", &Private::referencedByRelation);
1126         //%% string referencesRelation
1127         s_inst.addProperty("referencesRelation",   &Private::referencesRelation);
1128         //%% markerstring inheritedFrom
1129         s_inst.addProperty("inheritedFrom",      &Private::inheritedFrom);
1130         //%% string addtionalInheritedMembers
1131         s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers);
1132         //%% string includeDependencyGraph:container_name
1133         s_inst.addProperty("includeDependencyGraph",&Private::includeDependencyGraph);
1134         //%% string includedByDependencyGraph
1135         s_inst.addProperty("includedByDependencyGraph",&Private::includedByDependencyGraph);
1136         //%% string gotoSourceCode
1137         s_inst.addProperty("gotoSourceCode",     &Private::gotoSourceCode);
1138         //%% string gotoDocumentation
1139         s_inst.addProperty("gotoDocumentation",  &Private::gotoDocumentation);
1140         //%% string constantgroups
1141         s_inst.addProperty("constantgroups",     &Private::constantgroups);
1142         //%% string classDocumentation
1143         s_inst.addProperty("classDocumentation", &Private::classDocumentation);
1144         //%% string namespaceDocumentation
1145         s_inst.addProperty("namespaceDocumentation", &Private::namespaceDocumentation);
1146         //%% string moduleDocumentation
1147         s_inst.addProperty("moduleDocumentation",&Private::moduleDocumentation);
1148         //%% string fileDocumentation
1149         s_inst.addProperty("fileDocumentation",  &Private::fileDocumentation);
1150         //%% string compoundMembers
1151         s_inst.addProperty("compoundMembers",    &Private::compoundMembers);
1152         //%% string detailLevel
1153         s_inst.addProperty("detailLevel",        &Private::detailLevel);
1154         //%% string fileListDescription
1155         s_inst.addProperty("fileListDescription",&Private::fileListDescription);
1156         //%% string namespaceListDescription
1157         s_inst.addProperty("namespaceListDescription",&Private::namespaceListDescription);
1158         //%% string directories
1159         s_inst.addProperty("directories",        &Private::directories);
1160         //%% string moduleDescription
1161         s_inst.addProperty("modulesDescription", &Private::modulesDescription);
1162         //%% string all
1163         s_inst.addProperty("all",                &Private::all);
1164         //%% string functions
1165         s_inst.addProperty("functions",          &Private::functions);
1166         //%% string variables
1167         s_inst.addProperty("variables",          &Private::variables);
1168         //%% string typedefs
1169         s_inst.addProperty("typedefs",           &Private::typedefs);
1170         //%% string enums
1171         s_inst.addProperty("enums",              &Private::enums);
1172         //%% string enumValues
1173         s_inst.addProperty("enumValues",         &Private::enumerationValues);
1174         //%% string properties
1175         s_inst.addProperty("properties",         &Private::properties);
1176         //%% string events
1177         s_inst.addProperty("events",             &Private::events);
1178         //%% string related
1179         s_inst.addProperty("related",            &Private::related);
1180         //%% string macros
1181         s_inst.addProperty("macros",             &Private::macros);
1182         //%% string namespaceMembersDescription
1183         s_inst.addProperty("namespaceMembersDescription",&Private::namespaceMembersDescription);
1184         //%% string classHierarchyDescription
1185         s_inst.addProperty("classHierarchyDescription",&Private::classHierarchyDescription);
1186         //%% string gotoGraphicalHierarchy
1187         s_inst.addProperty("gotoGraphicalHierarchy",&Private::gotoGraphicalHierarchy);
1188         //%% string gotoTextualHierarchy
1189         s_inst.addProperty("gotoTextualHierarchy",&Private::gotoTextualHierarchy);
1190         //%% string loading
1191         s_inst.addProperty("loading",            &Private::loading);
1192         //%% string searching
1193         s_inst.addProperty("searching",          &Private::searching);
1194         //%% string noMatches
1195         s_inst.addProperty("noMatches",          &Private::noMatches);
1196         //%% string enumValue
1197         s_inst.addProperty("enumValue",          &Private::enumValue);
1198         //%% string enumName
1199         s_inst.addProperty("enumName",           &Private::enumName);
1200         //%% string referenceManual
1201         s_inst.addProperty("referenceManual",    &Private::referenceManual);
1202         //%% string index
1203         s_inst.addProperty("index",              &Private::index);
1204         //%% string panelSyncOn
1205         s_inst.addProperty("panelSyncOn",        &Private::panelSyncOn);
1206         //%% string panelSyncOff
1207         s_inst.addProperty("panelSyncOff",       &Private::panelSyncOff);
1208         //%% string dirDependencyGraph
1209         s_inst.addProperty("dirDependencyGraphFor", &Private::dirDependencyGraphFor);
1210         //%% string providedByCategory
1211         s_inst.addProperty("providedByCategory", &Private::providedByCategory);
1212         //%% string extendsClass
1213         s_inst.addProperty("extendsClass",       &Private::extendsClass);
1214         //%% string examplesDescription
1215         s_inst.addProperty("examplesDescription",&Private::examplesDescription);
1216         //%% string langstring
1217         s_inst.addProperty("langString",         &Private::langString);
1218
1219         init=TRUE;
1220       }
1221
1222       m_javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
1223       m_fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
1224       m_vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
1225       m_sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
1226     }
1227     TemplateVariant get(const char *n) const
1228     {
1229       return s_inst.get(this,n);
1230     }
1231   private:
1232     bool m_javaOpt;
1233     bool m_fortranOpt;
1234     bool m_vhdlOpt;
1235     bool m_sliceOpt;
1236     static PropertyMapper<TranslateContext::Private> s_inst;
1237 };
1238 //%% }
1239
1240 PropertyMapper<TranslateContext::Private> TranslateContext::Private::s_inst;
1241
1242 TranslateContext::TranslateContext() : RefCountedContext("TranslateContext")
1243 {
1244   p = new Private;
1245 }
1246
1247 TranslateContext::~TranslateContext()
1248 {
1249   delete p;
1250 }
1251
1252 TemplateVariant TranslateContext::get(const char *n) const
1253 {
1254   return p->get(n);
1255 }
1256
1257 static TemplateVariant parseDoc(Definition *def,const QCString &file,int line,
1258                                 const QCString &relPath,const QCString &docStr,bool isBrief)
1259 {
1260   TemplateVariant result;
1261   DocRoot *root = validatingParseDoc(file,line,def,0,docStr,TRUE,FALSE,0,isBrief,FALSE);
1262   QGString docs;
1263   {
1264     FTextStream ts(&docs);
1265     switch (g_globals.outputFormat)
1266     {
1267       case ContextOutputFormat_Html:
1268         {
1269           HtmlCodeGenerator codeGen(ts,relPath);
1270           HtmlDocVisitor visitor(ts,codeGen,def);
1271           root->accept(&visitor);
1272         }
1273         break;
1274       case ContextOutputFormat_Latex:
1275         {
1276           LatexCodeGenerator codeGen(ts,relPath,file);
1277           LatexDocVisitor visitor(ts,codeGen,def->getDefFileExtension(),FALSE);
1278           root->accept(&visitor);
1279         }
1280         break;
1281       // TODO: support other generators
1282       default:
1283         err("context.cpp: output format not yet supported");
1284         break;
1285     }
1286   }
1287   bool isEmpty = root->isEmpty();
1288   if (isEmpty)
1289     result = "";
1290   else
1291     result = TemplateVariant(docs,TRUE);
1292   delete root;
1293   return result;
1294 }
1295
1296 static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const QCString &relPath,
1297                                  const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE)
1298 {
1299   ParserInterface *pIntf = Doxygen::parserManager->getParser(md->getDefFileExtension());
1300   pIntf->resetCodeParserState();
1301   QGString s;
1302   FTextStream t(&s);
1303   switch (g_globals.outputFormat)
1304   {
1305     case ContextOutputFormat_Html:
1306       {
1307         HtmlCodeGenerator codeGen(t,relPath);
1308         pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(),
1309             startLine,endLine,TRUE,md,showLineNumbers,md);
1310       }
1311       break;
1312     case ContextOutputFormat_Latex:
1313       {
1314         LatexCodeGenerator codeGen(t,relPath,md->docFile());
1315         pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(),
1316             startLine,endLine,TRUE,md,showLineNumbers,md);
1317       }
1318       break;
1319     // TODO: support other generators
1320     default:
1321       err("context.cpp: output format not yet supported");
1322       break;
1323   }
1324   return TemplateVariant(s.data(),TRUE);
1325 }
1326
1327 static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
1328 {
1329   static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
1330   ParserInterface *pIntf = Doxygen::parserManager->getParser(fd->getDefFileExtension());
1331   pIntf->resetCodeParserState();
1332   QGString s;
1333   FTextStream t(&s);
1334   switch (g_globals.outputFormat)
1335   {
1336     case ContextOutputFormat_Html:
1337       {
1338         HtmlCodeGenerator codeGen(t,relPath);
1339         pIntf->parseCode(codeGen,0,
1340               fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
1341               fd->getLanguage(),  // lang
1342               FALSE,              // isExampleBlock
1343               0,                  // exampleName
1344               fd,                 // fileDef
1345               -1,                 // startLine
1346               -1,                 // endLine
1347               FALSE,              // inlineFragment
1348               0,                  // memberDef
1349               TRUE,               // showLineNumbers
1350               0,                  // searchCtx
1351               TRUE                // collectXRefs, TODO: should become FALSE
1352               );
1353       }
1354       break;
1355     case ContextOutputFormat_Latex:
1356       {
1357         LatexCodeGenerator codeGen(t,relPath,fd->docFile());
1358         pIntf->parseCode(codeGen,0,
1359               fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
1360               fd->getLanguage(),  // lang
1361               FALSE,              // isExampleBlock
1362               0,                  // exampleName
1363               fd,                 // fileDef
1364               -1,                 // startLine
1365               -1,                 // endLine
1366               FALSE,              // inlineFragment
1367               0,                  // memberDef
1368               TRUE,               // showLineNumbers
1369               0,                  // searchCtx
1370               TRUE                // collectXRefs, TODO: should become FALSE
1371               );
1372       }
1373       break;
1374     // TODO: support other generators
1375     default:
1376       err("context.cpp: output format not yet supported");
1377       break;
1378   }
1379   return TemplateVariant(s.data(),TRUE);
1380 }
1381
1382 //------------------------------------------------------------------------
1383
1384 //%% struct Symbol: shared info for all symbols
1385 //%% {
1386 template<typename T>
1387 class DefinitionContext
1388 {
1389   public:
1390     DefinitionContext(Definition *d) : m_def(d)
1391     {
1392       assert(d!=0);
1393     }
1394     void addBaseProperties(PropertyMapper<T> &inst)
1395     {
1396       //%% string name: the name of the symbol
1397       inst.addProperty("name",&DefinitionContext::name);
1398       //%% string bareName: the bare name of the symbol with scope info
1399       inst.addProperty("bareName",&DefinitionContext::bareName);
1400       //%% string relPath: the relative path to the root of the output (CREATE_SUBDIRS)
1401       inst.addProperty("relPath",&DefinitionContext::relPath);
1402       //%% string fileName: the file name of the output file associated with the symbol (without extension)
1403       inst.addProperty("fileName",&DefinitionContext::fileName);
1404       //%% string anchor: anchor within the page
1405       inst.addProperty("anchor",&DefinitionContext::anchor);
1406       //%% string details: the detailed documentation for this symbol
1407       inst.addProperty("details",&DefinitionContext::details);
1408       //%% string brief: the brief description for this symbol
1409       inst.addProperty("brief",&DefinitionContext::brief);
1410       //%% string inbodyDocs: the documentation found in the body
1411       inst.addProperty("inbodyDocs",&DefinitionContext::inbodyDocs);
1412       //%% string sourceFileName: the file name of the source file (without extension)
1413       inst.addProperty("sourceFileName",&DefinitionContext::sourceFileName);
1414       //%% bool isLinkable: can the symbol be linked to?
1415       inst.addProperty("isLinkable",&DefinitionContext::isLinkable);
1416       //%% bool isLinkableInProject: can the symbol be linked within this project?
1417       inst.addProperty("isLinkableInProject",&DefinitionContext::isLinkableInProject);
1418       //%% int dynSectionId: identifier that can be used for collapsible sections
1419       inst.addProperty("dynSectionId",&DefinitionContext::dynSectionId);
1420       //%% string language: the programming language in which the symbol is written
1421       inst.addProperty("language",&DefinitionContext::language);
1422       //%% string sourceDef: A link to the source definition
1423       inst.addProperty("sourceDef",&DefinitionContext::sourceDef);
1424       //%% list[Definition] navigationPath: Breadcrumb navigation path to this item
1425       inst.addProperty("navigationPath",&DefinitionContext::navigationPath);
1426       //%% string kind: Kind of compound object: class, namespace, module, package, page, dir
1427       inst.addProperty("compoundKind",&DefinitionContext::compoundKind);
1428       //%% bool isReference: is this definition imported via a tag file
1429       inst.addProperty("isReference",&DefinitionContext::isReference);
1430       //%% string externalReference: the link to the element in the remote documentation
1431       inst.addProperty("externalReference",&DefinitionContext::externalReference);
1432     }
1433     TemplateVariant fileName() const
1434     {
1435       return m_def->getOutputFileBase();
1436     }
1437     TemplateVariant anchor() const
1438     {
1439       return m_def->anchor();
1440     }
1441     TemplateVariant sourceFileName() const
1442     {
1443       return m_def->getSourceFileBase();
1444     }
1445     TemplateVariant isLinkable() const
1446     {
1447       return m_def->isLinkable();
1448     }
1449     TemplateVariant isLinkableInProject() const
1450     {
1451       return m_def->isLinkableInProject();
1452     }
1453     TemplateVariant name() const
1454     {
1455       return m_def->displayName(TRUE);
1456     }
1457     TemplateVariant bareName() const
1458     {
1459       return m_def->displayName(FALSE);
1460     }
1461     QCString relPathAsString() const
1462     {
1463       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
1464       return createSubdirs ? QCString("../../") : QCString("");
1465     }
1466     virtual TemplateVariant relPath() const
1467     {
1468       return relPathAsString();
1469     }
1470     TemplateVariant details() const
1471     {
1472       Cachable &cache = getCache();
1473       if (!cache.details || g_globals.outputFormat!=cache.detailsOutputFormat)
1474       {
1475         cache.details.reset(new TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),
1476                                             relPathAsString(),m_def->documentation(),FALSE)));
1477         cache.detailsOutputFormat = g_globals.outputFormat;
1478       }
1479       return *cache.details;
1480     }
1481     TemplateVariant brief() const
1482     {
1483       Cachable &cache = getCache();
1484       if (!cache.brief || g_globals.outputFormat!=cache.briefOutputFormat)
1485       {
1486         if (m_def->hasBriefDescription())
1487         {
1488           cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
1489                              relPathAsString(),m_def->briefDescription(),TRUE)));
1490           cache.briefOutputFormat = g_globals.outputFormat;
1491         }
1492         else
1493         {
1494           cache.brief.reset(new TemplateVariant(""));
1495         }
1496       }
1497       return *cache.brief;
1498     }
1499     TemplateVariant inbodyDocs() const
1500     {
1501       Cachable &cache = getCache();
1502       if (!cache.inbodyDocs || g_globals.outputFormat!=cache.inbodyDocsOutputFormat)
1503       {
1504         if (!m_def->inbodyDocumentation().isEmpty())
1505         {
1506           cache.inbodyDocs.reset(new TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(),
1507                                            relPathAsString(),m_def->inbodyDocumentation(),FALSE)));
1508           cache.inbodyDocsOutputFormat = g_globals.outputFormat;
1509         }
1510         else
1511         {
1512           cache.inbodyDocs.reset(new TemplateVariant(""));
1513         }
1514       }
1515       return *cache.inbodyDocs;
1516     }
1517     TemplateVariant dynSectionId() const
1518     {
1519       return g_globals.dynSectionId;
1520     }
1521     TemplateVariant language() const
1522     {
1523       SrcLangExt lang = m_def->getLanguage();
1524       QCString result = "unknown";
1525       switch (lang)
1526       {
1527         case SrcLangExt_Unknown:  break;
1528         case SrcLangExt_IDL:      result="idl";      break;
1529         case SrcLangExt_Java:     result="java";     break;
1530         case SrcLangExt_CSharp:   result="csharp";   break;
1531         case SrcLangExt_D:        result="d";        break;
1532         case SrcLangExt_PHP:      result="php";      break;
1533         case SrcLangExt_ObjC:     result="objc";     break;
1534         case SrcLangExt_Cpp:      result="cpp";      break;
1535         case SrcLangExt_JS:       result="js";       break;
1536         case SrcLangExt_Python:   result="python";   break;
1537         case SrcLangExt_Fortran:  result="fortran";  break;
1538         case SrcLangExt_VHDL:     result="vhdl";     break;
1539         case SrcLangExt_XML:      result="xml";      break;
1540         case SrcLangExt_SQL:      result="sql";      break;
1541         case SrcLangExt_Tcl:      result="tcl";      break;
1542         case SrcLangExt_Markdown: result="markdown"; break;
1543         case SrcLangExt_Slice:    result="slice";    break;
1544       }
1545       return result;
1546     }
1547     TemplateVariant compoundKind() const
1548     {
1549       QCString result = "unspecified";
1550       switch (m_def->definitionType())
1551       {
1552         case DefinitionIntf::TypeClass:     result="class";     break;
1553         case DefinitionIntf::TypeFile:      result="file";      break;
1554         case DefinitionIntf::TypeNamespace: result="namespace"; break;
1555         case DefinitionIntf::TypeGroup:     result="module";    break;
1556         case DefinitionIntf::TypePackage:   result="package";   break;
1557         case DefinitionIntf::TypePage:      result="page";      break;
1558         case DefinitionIntf::TypeDir:       result="dir";       break;
1559         case DefinitionIntf::TypeMember: // fall through
1560         case DefinitionIntf::TypeSymbolList:
1561                 break;
1562       }
1563       return result;
1564     }
1565     TemplateVariant sourceDef() const
1566     {
1567       Cachable &cache = getCache();
1568       if (cache.sourceDef->count()==2)
1569       {
1570         return cache.sourceDef.get();
1571       }
1572       else
1573       {
1574         return FALSE;
1575       }
1576     }
1577     void fillPath(Definition *def,TemplateList *list) const
1578     {
1579       Definition *outerScope = def->getOuterScope();
1580       Definition::DefType type = def->definitionType();
1581       if (outerScope && outerScope!=Doxygen::globalScope)
1582       {
1583         fillPath(outerScope,list);
1584       }
1585       else if (type==Definition::TypeFile && ((const FileDef*)def)->getDirDef())
1586       {
1587         fillPath(((const FileDef*)def)->getDirDef(),list);
1588       }
1589       list->append(NavPathElemContext::alloc(def));
1590     }
1591     TemplateVariant navigationPath() const
1592     {
1593       Cachable &cache = getCache();
1594       if (!cache.navPath)
1595       {
1596         TemplateList *list = TemplateList::alloc();
1597         if (m_def->getOuterScope() && m_def->getOuterScope()!=Doxygen::globalScope)
1598         {
1599           fillPath(m_def->getOuterScope(),list);
1600         }
1601         else if (m_def->definitionType()==Definition::TypeFile && ((const FileDef *)m_def)->getDirDef())
1602         {
1603           fillPath(((const FileDef *)m_def)->getDirDef(),list);
1604         }
1605         cache.navPath.reset(list);
1606       }
1607       return cache.navPath.get();
1608     }
1609     TemplateVariant isReference() const
1610     {
1611       return m_def->isReference();
1612     }
1613     TemplateVariant externalReference() const
1614     {
1615       return m_def->externalReference(relPathAsString());
1616     }
1617
1618   protected:
1619     struct Cachable : public Definition::Cookie
1620     {
1621       Cachable(Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified),
1622                                   briefOutputFormat(ContextOutputFormat_Unspecified),
1623                                   inbodyDocsOutputFormat(ContextOutputFormat_Unspecified)
1624       {
1625         sourceDef.reset(TemplateList::alloc());
1626         lineLink.reset(TemplateStruct::alloc());
1627         fileLink.reset(TemplateStruct::alloc());
1628
1629         if (def && !def->getSourceFileBase().isEmpty())
1630         {
1631           lineLink->set("text",def->getStartBodyLine());
1632           lineLink->set("isLinkable",TRUE);
1633           lineLink->set("fileName",def->getSourceFileBase());
1634           lineLink->set("anchor",def->getSourceAnchor());
1635           lineLink->set("isReference",FALSE);
1636           lineLink->set("externalReference","");
1637           if (def->definitionType()==Definition::TypeFile)
1638           {
1639             fileLink->set("text",def->name());
1640           }
1641           else if (def->getBodyDef())
1642           {
1643             fileLink->set("text",def->getBodyDef()->name());
1644           }
1645           else
1646           {
1647             fileLink->set("text",def->displayName(TRUE));
1648           }
1649           fileLink->set("isLinkable",TRUE);
1650           fileLink->set("fileName",def->getSourceFileBase());
1651           fileLink->set("anchor",QCString());
1652           fileLink->set("isReference",FALSE);
1653           fileLink->set("externalReference","");
1654           sourceDef->append(lineLink.get());
1655           sourceDef->append(fileLink.get());
1656         }
1657       }
1658       ScopedPtr<TemplateVariant> details;
1659       ContextOutputFormat        detailsOutputFormat;
1660       ScopedPtr<TemplateVariant> brief;
1661       ContextOutputFormat        briefOutputFormat;
1662       ScopedPtr<TemplateVariant> inbodyDocs;
1663       ContextOutputFormat        inbodyDocsOutputFormat;
1664       SharedPtr<TemplateList>    navPath;
1665       SharedPtr<TemplateList>    sourceDef;
1666       SharedPtr<TemplateStruct>  fileLink;
1667       SharedPtr<TemplateStruct>  lineLink;
1668     };
1669
1670
1671   private:
1672     Cachable &getCache() const
1673     {
1674       Cachable *c = static_cast<Cachable*>(m_def->cookie());
1675       assert(c!=0);
1676       return *c;
1677     }
1678     Definition      *m_def;
1679 };
1680 //%% }
1681
1682 //------------------------------------------------------------------------
1683
1684 //%% struct IncludeInfo: include file information
1685 //%% {
1686 class IncludeInfoContext::Private
1687 {
1688   public:
1689     Private(const IncludeInfo *info,SrcLangExt lang) :
1690       m_info(info),
1691       m_lang(lang)
1692     {
1693       static bool init=FALSE;
1694       if (!init)
1695       {
1696         s_inst.addProperty("file",&Private::file);
1697         s_inst.addProperty("name",&Private::name);
1698         s_inst.addProperty("isImport",&Private::isImport);
1699         s_inst.addProperty("isLocal",&Private::isLocal);
1700         init=TRUE;
1701       }
1702     }
1703     TemplateVariant get(const char *n) const
1704     {
1705       return s_inst.get(this,n);
1706     }
1707     TemplateVariant isLocal() const
1708     {
1709       bool isIDLorJava = m_lang==SrcLangExt_IDL || m_lang==SrcLangExt_Java;
1710       return m_info->local || isIDLorJava;
1711     }
1712     TemplateVariant isImport() const
1713     {
1714       return m_info->imported || m_lang==SrcLangExt_ObjC;
1715     }
1716     TemplateVariant file() const
1717     {
1718       if (!m_fileContext && m_info && m_info->fileDef)
1719       {
1720         m_fileContext.reset(FileContext::alloc(m_info->fileDef));
1721       }
1722       if (m_fileContext)
1723       {
1724         return m_fileContext.get();
1725       }
1726       else
1727       {
1728         return FALSE;
1729       }
1730     }
1731     TemplateVariant name() const
1732     {
1733       return m_info->includeName;
1734     }
1735   private:
1736     const IncludeInfo *m_info;
1737     mutable SharedPtr<FileContext> m_fileContext;
1738     SrcLangExt m_lang;
1739     static PropertyMapper<IncludeInfoContext::Private> s_inst;
1740 };
1741
1742 PropertyMapper<IncludeInfoContext::Private> IncludeInfoContext::Private::s_inst;
1743
1744 IncludeInfoContext::IncludeInfoContext(const IncludeInfo *info,SrcLangExt lang) : RefCountedContext("IncludeContext")
1745 {
1746   p = new Private(info,lang);
1747 }
1748
1749 IncludeInfoContext::~IncludeInfoContext()
1750 {
1751   delete p;
1752 }
1753
1754 TemplateVariant IncludeInfoContext::get(const char *n) const
1755 {
1756   return p->get(n);
1757 }
1758 //%% }
1759
1760 //------------------------------------------------------------------------
1761
1762 //%% list IncludeInfoList[Class] : list of nested classes
1763 class IncludeInfoListContext::Private : public GenericNodeListContext
1764 {
1765   public:
1766     Private(const QList<IncludeInfo> &list,SrcLangExt lang)
1767     {
1768       QListIterator<IncludeInfo> li(list);
1769       IncludeInfo *ii;
1770       for (li.toFirst();(ii=li.current());++li)
1771       {
1772         if (!ii->indirect)
1773         {
1774           append(IncludeInfoContext::alloc(ii,lang));
1775         }
1776       }
1777     }
1778 };
1779
1780 IncludeInfoListContext::IncludeInfoListContext(const QList<IncludeInfo> &list,SrcLangExt lang) : RefCountedContext("IncludeListContext")
1781 {
1782   p = new Private(list,lang);
1783 }
1784
1785 IncludeInfoListContext::~IncludeInfoListContext()
1786 {
1787   delete p;
1788 }
1789
1790 // TemplateListIntf
1791 int IncludeInfoListContext::count() const
1792 {
1793   return p->count();
1794 }
1795
1796 TemplateVariant IncludeInfoListContext::at(int index) const
1797 {
1798   return p->at(index);
1799 }
1800
1801 TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const
1802 {
1803   return p->createIterator();
1804 }
1805
1806 //------------------------------------------------------------------------
1807
1808 //%% struct Class(Symbol): class information
1809 //%% {
1810 class ClassContext::Private : public DefinitionContext<ClassContext::Private>
1811 {
1812   public:
1813     Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
1814        m_classDef(cd)
1815     {
1816       static bool init=FALSE;
1817       if (!init)
1818       {
1819         addBaseProperties(s_inst);
1820         s_inst.addProperty("title",                     &Private::title);
1821         s_inst.addProperty("highlight",                 &Private::highlight);
1822         s_inst.addProperty("subhighlight",              &Private::subHighlight);
1823         s_inst.addProperty("hasDetails",                &Private::hasDetails);
1824         s_inst.addProperty("generatedFromFiles",        &Private::generatedFromFiles);
1825         s_inst.addProperty("usedFiles",                 &Private::usedFiles);
1826         s_inst.addProperty("hasInheritanceDiagram",     &Private::hasInheritanceDiagram);
1827         s_inst.addProperty("inheritanceDiagram",        &Private::inheritanceDiagram);
1828         s_inst.addProperty("hasCollaborationDiagram",   &Private::hasCollaborationDiagram);
1829         s_inst.addProperty("collaborationDiagram",      &Private::collaborationDiagram);
1830         s_inst.addProperty("includeInfo",               &Private::includeInfo);
1831         s_inst.addProperty("inherits",                  &Private::inherits);
1832         s_inst.addProperty("inheritedBy",               &Private::inheritedBy);
1833         s_inst.addProperty("unoIDLServices",            &Private::unoIDLServices);
1834         s_inst.addProperty("unoIDLInterfaces",          &Private::unoIDLInterfaces);
1835         s_inst.addProperty("signals",                   &Private::signals);
1836         s_inst.addProperty("publicTypes",               &Private::publicTypes);
1837         s_inst.addProperty("publicMethods",             &Private::publicMethods);
1838         s_inst.addProperty("publicStaticMethods",       &Private::publicStaticMethods);
1839         s_inst.addProperty("publicAttributes",          &Private::publicAttributes);
1840         s_inst.addProperty("publicStaticAttributes",    &Private::publicStaticAttributes);
1841         s_inst.addProperty("publicSlots",               &Private::publicSlots);
1842         s_inst.addProperty("protectedTypes",            &Private::protectedTypes);
1843         s_inst.addProperty("protectedMethods",          &Private::protectedMethods);
1844         s_inst.addProperty("protectedStaticMethods",    &Private::protectedStaticMethods);
1845         s_inst.addProperty("protectedAttributes",       &Private::protectedAttributes);
1846         s_inst.addProperty("protectedStaticAttributes", &Private::protectedStaticAttributes);
1847         s_inst.addProperty("protectedSlots",            &Private::protectedSlots);
1848         s_inst.addProperty("privateTypes",              &Private::privateTypes);
1849         s_inst.addProperty("privateMethods",            &Private::privateMethods);
1850         s_inst.addProperty("privateStaticMethods",      &Private::privateStaticMethods);
1851         s_inst.addProperty("privateAttributes",         &Private::privateAttributes);
1852         s_inst.addProperty("privateStaticAttributes",   &Private::privateStaticAttributes);
1853         s_inst.addProperty("privateSlots",              &Private::privateSlots);
1854         s_inst.addProperty("packageTypes",              &Private::packageTypes);
1855         s_inst.addProperty("packageMethods",            &Private::packageMethods);
1856         s_inst.addProperty("packageStaticMethods",      &Private::packageStaticMethods);
1857         s_inst.addProperty("packageAttributes",         &Private::packageAttributes);
1858         s_inst.addProperty("packageStaticAttributes",   &Private::packageStaticAttributes);
1859         s_inst.addProperty("properties",                &Private::properties);
1860         s_inst.addProperty("events",                    &Private::events);
1861         s_inst.addProperty("friends",                   &Private::friends);
1862         s_inst.addProperty("related",                   &Private::related);
1863         s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
1864         s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
1865         s_inst.addProperty("detailedServices",          &Private::detailedServices);
1866         s_inst.addProperty("detailedInterfaces",        &Private::detailedInterfaces);
1867         s_inst.addProperty("detailedConstructors",      &Private::detailedConstructors);
1868         s_inst.addProperty("detailedMethods",           &Private::detailedMethods);
1869         s_inst.addProperty("detailedRelated",           &Private::detailedRelated);
1870         s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
1871         s_inst.addProperty("detailedProperties",        &Private::detailedProperties);
1872         s_inst.addProperty("detailedEvents",            &Private::detailedEvents);
1873         s_inst.addProperty("classes",                   &Private::classes);
1874         s_inst.addProperty("innerClasses",              &Private::innerClasses);
1875         s_inst.addProperty("compoundType",              &Private::compoundType);
1876         s_inst.addProperty("templateDecls",             &Private::templateDecls);
1877         s_inst.addProperty("typeConstraints",           &Private::typeConstraints);
1878         s_inst.addProperty("examples",                  &Private::examples);
1879         s_inst.addProperty("members",                   &Private::members);
1880         s_inst.addProperty("allMembersList",            &Private::allMembersList);
1881         s_inst.addProperty("allMembersFileName",        &Private::allMembersFileName);
1882         s_inst.addProperty("memberGroups",              &Private::memberGroups);
1883         s_inst.addProperty("additionalInheritedMembers",&Private::additionalInheritedMembers);
1884         s_inst.addProperty("isSimple",                  &Private::isSimple);
1885         s_inst.addProperty("categoryOf",                &Private::categoryOf);
1886         init=TRUE;
1887       }
1888       if (!cd->cookie()) { cd->setCookie(new ClassContext::Private::Cachable(cd)); }
1889     }
1890     virtual ~Private() {}
1891     TemplateVariant get(const char *n) const
1892     {
1893       return s_inst.get(this,n);
1894     }
1895     TemplateVariant title() const
1896     {
1897       return TemplateVariant(m_classDef->title());
1898     }
1899     TemplateVariant highlight() const
1900     {
1901       return TemplateVariant("classes");
1902     }
1903     TemplateVariant subHighlight() const
1904     {
1905       return TemplateVariant("");
1906     }
1907     TemplateVariant hasDetails() const
1908     {
1909       return m_classDef->hasDetailedDescription();
1910     }
1911     TemplateVariant generatedFromFiles() const
1912     {
1913       return m_classDef->generatedFromFiles();
1914     }
1915     TemplateVariant usedFiles() const
1916     {
1917       Cachable &cache = getCache();
1918       if (!cache.usedFiles)
1919       {
1920         cache.usedFiles.reset(UsedFilesContext::alloc(m_classDef));
1921       }
1922       return cache.usedFiles.get();
1923     }
1924     DotClassGraph *getClassGraph() const
1925     {
1926       Cachable &cache = getCache();
1927       if (!cache.classGraph)
1928       {
1929         cache.classGraph.reset(new DotClassGraph(m_classDef,DotNode::Inheritance));
1930       }
1931       return cache.classGraph.get();
1932     }
1933     int numInheritanceNodes() const
1934     {
1935       Cachable &cache = getCache();
1936       if (cache.inheritanceNodes==-1)
1937       {
1938         cache.inheritanceNodes=m_classDef->countInheritanceNodes();
1939       }
1940       return cache.inheritanceNodes>0;
1941     }
1942     TemplateVariant hasInheritanceDiagram() const
1943     {
1944       bool result=FALSE;
1945       static bool haveDot       = Config_getBool(HAVE_DOT);
1946       static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS);
1947       static bool classGraph    = Config_getBool(CLASS_GRAPH);
1948       if (haveDot && (classDiagrams || classGraph))
1949       {
1950         DotClassGraph *cg = getClassGraph();
1951         result = !cg->isTrivial() && !cg->isTooBig();
1952       }
1953       else if (classDiagrams)
1954       {
1955         result = numInheritanceNodes()>0;
1956       }
1957       return result;
1958     }
1959     TemplateVariant inheritanceDiagram() const
1960     {
1961       QGString result;
1962       static bool haveDot       = Config_getBool(HAVE_DOT);
1963       static bool classDiagrams = Config_getBool(CLASS_DIAGRAMS);
1964       static bool classGraph    = Config_getBool(CLASS_GRAPH);
1965       if (haveDot && (classDiagrams || classGraph))
1966       {
1967         DotClassGraph *cg = getClassGraph();
1968         FTextStream t(&result);
1969         switch (g_globals.outputFormat)
1970         {
1971           case ContextOutputFormat_Html:
1972             {
1973               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
1974                              g_globals.outputDir,
1975                              g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
1976                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1977                             );
1978             }
1979             break;
1980           case ContextOutputFormat_Latex:
1981             {
1982               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
1983                              g_globals.outputDir,
1984                              g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+".tex",
1985                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
1986                             );
1987             }
1988             break;
1989             // TODO: support other generators
1990           default:
1991             err("context.cpp: output format not yet supported");
1992             break;
1993         }
1994         g_globals.dynSectionId++;
1995       }
1996       else if (classDiagrams)
1997       {
1998         ClassDiagram d(m_classDef);
1999         FTextStream t(&result);
2000         switch (g_globals.outputFormat)
2001         {
2002           case ContextOutputFormat_Html:
2003             {
2004               QGString result;
2005               FTextStream tt(&result);
2006
2007               QCString name = convertToHtml(m_classDef->displayName());
2008               d.writeImage(tt,g_globals.outputDir,
2009                            relPathAsString(),
2010                            m_classDef->getOutputFileBase());
2011               if (!result.isEmpty())
2012               {
2013                 t << "<div class=\"center\">" << endl;
2014                 t << "  <img src=\"";
2015                 t << relPathAsString() << m_classDef->getOutputFileBase();
2016                 t << ".png\" usemap=\"#" << convertToId(name) << "_map\" alt=\"\"/>" << endl;
2017                 t << "  <map id=\"" << convertToId(name) << "_map\" name=\"" << convertToId(name) << "_map\">" << endl;
2018                 t << result;
2019                 t << "  </map>" << endl;
2020                 t << "</div>";
2021               }
2022               else
2023               {
2024                 t << "<div class=\"center\">" << endl;
2025                 t << "  <img src=\"";
2026                 t << relPathAsString() << m_classDef->getOutputFileBase();
2027                 t << ".png\" alt=\"\"/>" << endl;
2028                 t << "</div>";
2029               }
2030             }
2031             break;
2032           case ContextOutputFormat_Latex:
2033             {
2034               d.writeFigure(t,g_globals.outputDir,m_classDef->getOutputFileBase());
2035             }
2036             break;
2037             // TODO: support other generators
2038           default:
2039             err("context.cpp: output format not yet supported");
2040             break;
2041         }
2042         g_globals.dynSectionId++;
2043       }
2044       return TemplateVariant(result.data(),TRUE);
2045     }
2046     DotClassGraph *getCollaborationGraph() const
2047     {
2048       Cachable &cache = getCache();
2049       if (!cache.collaborationGraph)
2050       {
2051         cache.collaborationGraph.reset(new DotClassGraph(m_classDef,DotNode::Collaboration));
2052       }
2053       return cache.collaborationGraph.get();
2054     }
2055     TemplateVariant hasCollaborationDiagram() const
2056     {
2057       static bool haveDot = Config_getBool(HAVE_DOT);
2058       return haveDot && !getCollaborationGraph()->isTrivial();
2059     }
2060     TemplateVariant collaborationDiagram() const
2061     {
2062       static bool haveDot = Config_getBool(HAVE_DOT);
2063       QGString result;
2064       if (haveDot)
2065       {
2066         DotClassGraph *cg = getCollaborationGraph();
2067         FTextStream t(&result);
2068         switch (g_globals.outputFormat)
2069         {
2070           case ContextOutputFormat_Html:
2071             {
2072               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
2073                              g_globals.outputDir,
2074                              g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
2075                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
2076                             );
2077             }
2078             break;
2079           case ContextOutputFormat_Latex:
2080             {
2081               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
2082                              g_globals.outputDir,
2083                              g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+".tex",
2084                              relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
2085                             );
2086             }
2087             break;
2088             // TODO: support other generators
2089           default:
2090             err("context.cpp: output format not yet supported");
2091             break;
2092         }
2093         g_globals.dynSectionId++;
2094       }
2095       return TemplateVariant(result.data(),TRUE);
2096     }
2097
2098     TemplateVariant includeInfo() const
2099     {
2100       Cachable &cache = getCache();
2101       if (!cache.includeInfo && m_classDef->includeInfo())
2102       {
2103         cache.includeInfo.reset(IncludeInfoContext::alloc(m_classDef->includeInfo(),m_classDef->getLanguage()));
2104       }
2105       if (cache.includeInfo)
2106       {
2107         return cache.includeInfo.get();
2108       }
2109       else
2110       {
2111         return TemplateVariant(FALSE);
2112       }
2113     }
2114     TemplateVariant inherits() const
2115     {
2116       Cachable &cache = getCache();
2117       if (!cache.inheritsList)
2118       {
2119         cache.inheritsList.reset(InheritanceListContext::alloc(m_classDef->baseClasses(),TRUE));
2120       }
2121       return cache.inheritsList.get();
2122     }
2123     TemplateVariant inheritedBy() const
2124     {
2125       Cachable &cache = getCache();
2126       if (!cache.inheritedByList)
2127       {
2128         cache.inheritedByList.reset(InheritanceListContext::alloc(m_classDef->subClasses(),FALSE));
2129       }
2130       return cache.inheritedByList.get();
2131     }
2132     TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
2133                                   MemberListType type,const char *title,bool detailed=FALSE) const
2134     {
2135       if (!list)
2136       {
2137         MemberList *ml = m_classDef->getMemberList(type);
2138         if (ml)
2139         {
2140           list.reset(MemberListInfoContext::alloc(m_classDef,relPathAsString(),ml,title,""));
2141         }
2142       }
2143       if (list)
2144       {
2145         return list.get();
2146       }
2147       else
2148       {
2149         return TemplateVariant(FALSE);
2150       }
2151     }
2152     TemplateVariant unoIDLServices() const
2153     {
2154       return getMemberList(getCache().unoIDLServices,MemberListType_services,theTranslator->trServices());
2155     }
2156     TemplateVariant unoIDLInterfaces() const
2157     {
2158       return getMemberList(getCache().unoIDLInterfaces,MemberListType_interfaces,theTranslator->trInterfaces());
2159     }
2160     TemplateVariant signals() const
2161     {
2162       return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals());
2163     }
2164     TemplateVariant publicTypes() const
2165     {
2166       return getMemberList(getCache().publicTypes,MemberListType_pubTypes,theTranslator->trPublicTypes());
2167     }
2168     TemplateVariant publicMethods() const
2169     {
2170       return getMemberList(getCache().publicMethods,MemberListType_pubMethods,
2171           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
2172                                                      : theTranslator->trPublicMembers());
2173     }
2174     TemplateVariant publicStaticMethods() const
2175     {
2176       return getMemberList(getCache().publicStaticMethods,MemberListType_pubStaticMethods,
2177           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
2178                                                      : theTranslator->trStaticPublicMembers());
2179     }
2180     TemplateVariant publicAttributes() const
2181     {
2182       return getMemberList(getCache().publicAttributes,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
2183     }
2184     TemplateVariant publicStaticAttributes() const
2185     {
2186       return getMemberList(getCache().publicStaticAttributes,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
2187     }
2188     TemplateVariant publicSlots() const
2189     {
2190       return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots());
2191     }
2192     TemplateVariant protectedTypes() const
2193     {
2194       return getMemberList(getCache().protectedTypes,MemberListType_proTypes,theTranslator->trProtectedTypes());
2195     }
2196     TemplateVariant protectedMethods() const
2197     {
2198       return getMemberList(getCache().protectedMethods,MemberListType_proMethods,theTranslator->trProtectedMembers());
2199     }
2200     TemplateVariant protectedStaticMethods() const
2201     {
2202       return getMemberList(getCache().protectedStaticMethods,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
2203     }
2204     TemplateVariant protectedAttributes() const
2205     {
2206       return getMemberList(getCache().protectedAttributes,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
2207     }
2208     TemplateVariant protectedStaticAttributes() const
2209     {
2210       return getMemberList(getCache().protectedStaticAttributes,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
2211     }
2212     TemplateVariant protectedSlots() const
2213     {
2214       return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots());
2215     }
2216     TemplateVariant privateTypes() const
2217     {
2218       return getMemberList(getCache().privateTypes,MemberListType_priTypes,theTranslator->trPrivateTypes());
2219     }
2220     TemplateVariant privateSlots() const
2221     {
2222       return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots());
2223     }
2224     TemplateVariant privateMethods() const
2225     {
2226       return getMemberList(getCache().privateMethods,MemberListType_priMethods,theTranslator->trPrivateMembers());
2227     }
2228     TemplateVariant privateStaticMethods() const
2229     {
2230       return getMemberList(getCache().privateStaticMethods,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
2231     }
2232     TemplateVariant privateAttributes() const
2233     {
2234       return getMemberList(getCache().privateAttributes,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
2235     }
2236     TemplateVariant privateStaticAttributes() const
2237     {
2238       return getMemberList(getCache().privateStaticAttributes,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
2239     }
2240     TemplateVariant packageTypes() const
2241     {
2242       return getMemberList(getCache().packageTypes,MemberListType_pacTypes,theTranslator->trPackageTypes());
2243     }
2244     TemplateVariant packageMethods() const
2245     {
2246       return getMemberList(getCache().packageMethods,MemberListType_pacMethods,theTranslator->trPackageMembers());
2247     }
2248     TemplateVariant packageStaticMethods() const
2249     {
2250       return getMemberList(getCache().packageStaticMethods,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
2251     }
2252     TemplateVariant packageAttributes() const
2253     {
2254       return getMemberList(getCache().packageAttributes,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
2255     }
2256     TemplateVariant packageStaticAttributes() const
2257     {
2258       return getMemberList(getCache().packageStaticAttributes,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
2259     }
2260     TemplateVariant properties() const
2261     {
2262       return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties());
2263     }
2264     TemplateVariant events() const
2265     {
2266       return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents());
2267     }
2268     TemplateVariant friends() const
2269     {
2270       return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends());
2271     }
2272     TemplateVariant related() const
2273     {
2274       return getMemberList(getCache().related,MemberListType_related,theTranslator->trRelatedFunctions());
2275     }
2276     TemplateVariant detailedTypedefs() const
2277     {
2278       return getMemberList(getCache().detailedTypedefs,MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation(),TRUE);
2279     }
2280     TemplateVariant detailedEnums() const
2281     {
2282       return getMemberList(getCache().detailedEnums,MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation(),TRUE);
2283     }
2284     TemplateVariant detailedServices() const
2285     {
2286       return getMemberList(getCache().detailedServices,MemberListType_serviceMembers,theTranslator->trServices(),TRUE);
2287     }
2288     TemplateVariant detailedInterfaces() const
2289     {
2290       return getMemberList(getCache().detailedInterfaces,MemberListType_interfaceMembers,theTranslator->trInterfaces(),TRUE);
2291     }
2292     TemplateVariant detailedConstructors() const
2293     {
2294       return getMemberList(getCache().detailedConstructors,MemberListType_constructors,theTranslator->trConstructorDocumentation(),TRUE);
2295     }
2296     TemplateVariant detailedMethods() const
2297     {
2298       return getMemberList(getCache().detailedMethods,MemberListType_functionMembers,theTranslator->trMemberFunctionDocumentation(),TRUE);
2299     }
2300     TemplateVariant detailedRelated() const
2301     {
2302       return getMemberList(getCache().detailedRelated,MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation(),TRUE);
2303     }
2304     TemplateVariant detailedVariables() const
2305     {
2306       return getMemberList(getCache().detailedVariables,MemberListType_variableMembers,theTranslator->trMemberDataDocumentation(),TRUE);
2307     }
2308     TemplateVariant detailedProperties() const
2309     {
2310       return getMemberList(getCache().detailedProperties,MemberListType_propertyMembers,theTranslator->trPropertyDocumentation(),TRUE);
2311     }
2312     TemplateVariant detailedEvents() const
2313     {
2314       return getMemberList(getCache().detailedEvents,MemberListType_eventMembers,theTranslator->trEventDocumentation(),TRUE);
2315     }
2316     TemplateVariant classes() const
2317     {
2318       Cachable &cache = getCache();
2319       if (!cache.classes)
2320       {
2321         TemplateList *classList = TemplateList::alloc();
2322         if (m_classDef->getClassSDict())
2323         {
2324           ClassSDict::Iterator sdi(*m_classDef->getClassSDict());
2325           ClassDef *cd;
2326           for (sdi.toFirst();(cd=sdi.current());++sdi)
2327           {
2328             if (cd->visibleInParentsDeclList())
2329             {
2330               classList->append(ClassContext::alloc(cd));
2331             }
2332           }
2333         }
2334         cache.classes.reset(classList);
2335       }
2336       return cache.classes.get();
2337     }
2338     TemplateVariant innerClasses() const
2339     {
2340       Cachable &cache = getCache();
2341       if (!cache.innerClasses)
2342       {
2343         TemplateList *classList = TemplateList::alloc();
2344         if (m_classDef->getClassSDict())
2345         {
2346           ClassSDict::Iterator sdi(*m_classDef->getClassSDict());
2347           ClassDef *cd;
2348           for (sdi.toFirst();(cd=sdi.current());++sdi)
2349           {
2350             if (cd->name().find('@')==-1 &&
2351                 cd->isLinkableInProject() &&
2352                 cd->isEmbeddedInOuterScope() &&
2353                 cd->partOfGroups()==0
2354                )
2355             {
2356               classList->append(ClassContext::alloc(cd));
2357             }
2358           }
2359         }
2360         cache.innerClasses.reset(classList);
2361       }
2362       return cache.innerClasses.get();
2363     }
2364     TemplateVariant compoundType() const
2365     {
2366       return m_classDef->compoundTypeString();
2367     }
2368     void addTemplateDecls(Definition *d,TemplateList *tl) const
2369     {
2370       if (d->definitionType()==Definition::TypeClass)
2371       {
2372         Definition *parent = d->getOuterScope();
2373         if (parent)
2374         {
2375           addTemplateDecls(parent,tl);
2376         }
2377         ClassDef *cd=(ClassDef *)d;
2378         if (cd->templateArguments())
2379         {
2380           ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString());
2381           // since a TemplateVariant does take ownership of the object, we add it
2382           // a separate list just to be able to delete it and avoid a memory leak
2383           tl->append(al);
2384         }
2385       }
2386     }
2387     void addExamples(TemplateList *list) const
2388     {
2389       if (m_classDef->hasExamples())
2390       {
2391         ExampleSDict::Iterator it(*m_classDef->exampleList());
2392         Example *ex;
2393         for (it.toFirst();(ex=it.current());++it)
2394         {
2395           TemplateStruct *s = TemplateStruct::alloc();
2396           s->set("text",ex->name);
2397           s->set("isLinkable",TRUE);
2398           s->set("anchor",ex->anchor);
2399           s->set("fileName",ex->file);
2400           s->set("isReference",FALSE);
2401           s->set("externalReference","");
2402           list->append(s);
2403         }
2404       }
2405     }
2406     TemplateVariant templateDecls() const
2407     {
2408       Cachable &cache = getCache();
2409       if (!cache.templateDecls)
2410       {
2411         TemplateList *tl = TemplateList::alloc();
2412         addTemplateDecls(m_classDef,tl);
2413         cache.templateDecls.reset(tl);
2414       }
2415       return cache.templateDecls.get();
2416     }
2417     TemplateVariant typeConstraints() const
2418     {
2419       if (m_classDef->typeConstraints())
2420       {
2421         Cachable &cache = getCache();
2422         if (!cache.typeConstraints && m_classDef->typeConstraints())
2423         {
2424           cache.typeConstraints.reset(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString()));
2425         }
2426         return cache.typeConstraints.get();
2427       }
2428       return FALSE;
2429     }
2430     TemplateVariant examples() const
2431     {
2432       Cachable &cache = getCache();
2433       if (!cache.examples)
2434       {
2435         TemplateList *exampleList = TemplateList::alloc();
2436         addExamples(exampleList);
2437         cache.examples.reset(exampleList);
2438       }
2439       return cache.examples.get();
2440     }
2441     void addMembers(ClassDef *cd,MemberListType lt) const
2442     {
2443       MemberList *ml = cd->getMemberList(lt);
2444       if (ml)
2445       {
2446         Cachable &cache = getCache();
2447         MemberListIterator li(*ml);
2448         const MemberDef *md;
2449         for (li.toFirst();(md=li.current());++li)
2450         {
2451           if (md->isBriefSectionVisible())
2452           {
2453             cache.allMembers.append(md);
2454           }
2455         }
2456       }
2457     }
2458     TemplateVariant members() const
2459     {
2460       Cachable &cache = getCache();
2461       if (!cache.members)
2462       {
2463         addMembers(m_classDef,MemberListType_pubTypes);
2464         addMembers(m_classDef,MemberListType_services);
2465         addMembers(m_classDef,MemberListType_interfaces);
2466         addMembers(m_classDef,MemberListType_pubSlots);
2467         addMembers(m_classDef,MemberListType_signals);
2468         addMembers(m_classDef,MemberListType_pubMethods);
2469         addMembers(m_classDef,MemberListType_pubStaticMethods);
2470         addMembers(m_classDef,MemberListType_pubAttribs);
2471         addMembers(m_classDef,MemberListType_pubStaticAttribs);
2472         addMembers(m_classDef,MemberListType_proTypes);
2473         addMembers(m_classDef,MemberListType_proSlots);
2474         addMembers(m_classDef,MemberListType_proMethods);
2475         addMembers(m_classDef,MemberListType_proStaticMethods);
2476         addMembers(m_classDef,MemberListType_proAttribs);
2477         addMembers(m_classDef,MemberListType_proStaticAttribs);
2478         addMembers(m_classDef,MemberListType_pacTypes);
2479         addMembers(m_classDef,MemberListType_pacMethods);
2480         addMembers(m_classDef,MemberListType_pacStaticMethods);
2481         addMembers(m_classDef,MemberListType_pacAttribs);
2482         addMembers(m_classDef,MemberListType_pacStaticAttribs);
2483         addMembers(m_classDef,MemberListType_properties);
2484         addMembers(m_classDef,MemberListType_events);
2485         addMembers(m_classDef,MemberListType_priTypes);
2486         addMembers(m_classDef,MemberListType_priSlots);
2487         addMembers(m_classDef,MemberListType_priMethods);
2488         addMembers(m_classDef,MemberListType_priStaticMethods);
2489         addMembers(m_classDef,MemberListType_priAttribs);
2490         addMembers(m_classDef,MemberListType_priStaticAttribs);
2491         addMembers(m_classDef,MemberListType_related);
2492         cache.members.reset(MemberListContext::alloc(&cache.allMembers));
2493       }
2494       return cache.members.get();
2495     }
2496     TemplateVariant allMembersList() const
2497     {
2498       Cachable &cache = getCache();
2499       if (!cache.allMembersList)
2500       {
2501         if (m_classDef->memberNameInfoSDict())
2502         {
2503           AllMembersListContext *ml = AllMembersListContext::alloc(m_classDef->memberNameInfoSDict());
2504           cache.allMembersList.reset(ml);
2505         }
2506         else
2507         {
2508           cache.allMembersList.reset(AllMembersListContext::alloc());
2509         }
2510       }
2511       return cache.allMembersList.get();
2512     }
2513     TemplateVariant allMembersFileName() const
2514     {
2515       return m_classDef->getMemberListFileName();
2516     }
2517     TemplateVariant memberGroups() const
2518     {
2519       Cachable &cache = getCache();
2520       if (!cache.memberGroups)
2521       {
2522         if (m_classDef->getMemberGroupSDict())
2523         {
2524           cache.memberGroups.reset(MemberGroupListContext::alloc(m_classDef,relPathAsString(),m_classDef->getMemberGroupSDict(),m_classDef->subGrouping()));
2525         }
2526         else
2527         {
2528           cache.memberGroups.reset(MemberGroupListContext::alloc());
2529         }
2530       }
2531       return cache.memberGroups.get();
2532     }
2533     TemplateVariant additionalInheritedMembers() const
2534     {
2535       Cachable &cache = getCache();
2536       if (!cache.additionalInheritedMembers)
2537       {
2538         InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc();
2539         ctx->addMemberList(m_classDef,MemberListType_pubTypes,theTranslator->trPublicTypes());
2540         ctx->addMemberList(m_classDef,MemberListType_services,theTranslator->trServices());
2541         ctx->addMemberList(m_classDef,MemberListType_interfaces,theTranslator->trInterfaces());
2542         ctx->addMemberList(m_classDef,MemberListType_pubSlots,theTranslator->trPublicSlots());
2543         ctx->addMemberList(m_classDef,MemberListType_signals,theTranslator->trSignals());
2544         ctx->addMemberList(m_classDef,MemberListType_pubMethods,
2545           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trInstanceMethods()
2546                                                      : theTranslator->trPublicMembers());
2547         ctx->addMemberList(m_classDef,MemberListType_pubStaticMethods,
2548           m_classDef->getLanguage()==SrcLangExt_ObjC ? theTranslator->trClassMethods()
2549                                                      : theTranslator->trStaticPublicMembers());
2550         ctx->addMemberList(m_classDef,MemberListType_pubAttribs,theTranslator->trPublicAttribs());
2551         ctx->addMemberList(m_classDef,MemberListType_pubStaticAttribs,theTranslator->trStaticPublicAttribs());
2552         ctx->addMemberList(m_classDef,MemberListType_proTypes,theTranslator->trProtectedTypes());
2553         ctx->addMemberList(m_classDef,MemberListType_proSlots,theTranslator->trProtectedSlots());
2554         ctx->addMemberList(m_classDef,MemberListType_proMethods,theTranslator->trProtectedMembers());
2555         ctx->addMemberList(m_classDef,MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers());
2556         ctx->addMemberList(m_classDef,MemberListType_proAttribs,theTranslator->trProtectedAttribs());
2557         ctx->addMemberList(m_classDef,MemberListType_proStaticAttribs,theTranslator->trStaticProtectedAttribs());
2558         ctx->addMemberList(m_classDef,MemberListType_pacTypes,theTranslator->trPackageTypes());
2559         ctx->addMemberList(m_classDef,MemberListType_pacMethods,theTranslator->trPackageMembers());
2560         ctx->addMemberList(m_classDef,MemberListType_pacStaticMethods,theTranslator->trStaticPackageMembers());
2561         ctx->addMemberList(m_classDef,MemberListType_pacAttribs,theTranslator->trPackageAttribs());
2562         ctx->addMemberList(m_classDef,MemberListType_pacStaticAttribs,theTranslator->trStaticPackageAttribs());
2563         ctx->addMemberList(m_classDef,MemberListType_properties,theTranslator->trProperties());
2564         ctx->addMemberList(m_classDef,MemberListType_events,theTranslator->trEvents());
2565         ctx->addMemberList(m_classDef,MemberListType_priTypes,theTranslator->trPrivateTypes());
2566         ctx->addMemberList(m_classDef,MemberListType_priSlots,theTranslator->trPrivateSlots());
2567         ctx->addMemberList(m_classDef,MemberListType_priMethods,theTranslator->trPrivateMembers());
2568         ctx->addMemberList(m_classDef,MemberListType_priStaticMethods,theTranslator->trStaticPrivateMembers());
2569         ctx->addMemberList(m_classDef,MemberListType_priAttribs,theTranslator->trPrivateAttribs());
2570         ctx->addMemberList(m_classDef,MemberListType_priStaticAttribs,theTranslator->trStaticPrivateAttribs());
2571         ctx->addMemberList(m_classDef,MemberListType_related,theTranslator->trRelatedFunctions());
2572         cache.additionalInheritedMembers.reset(ctx);
2573       }
2574       return cache.additionalInheritedMembers.get();
2575     }
2576     TemplateVariant isSimple() const
2577     {
2578       return m_classDef->isSimple();
2579     }
2580     TemplateVariant categoryOf() const
2581     {
2582       Cachable &cache = getCache();
2583       if (!cache.categoryOf && m_classDef->categoryOf())
2584       {
2585         cache.categoryOf.reset(ClassContext::alloc(m_classDef->categoryOf()));
2586       }
2587       if (cache.categoryOf)
2588       {
2589         return cache.categoryOf.get();
2590       }
2591       else
2592       {
2593         return TemplateVariant(FALSE);
2594       }
2595     }
2596
2597   private:
2598     ClassDef *m_classDef;
2599     struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable
2600     {
2601       Cachable(ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd),
2602                                inheritanceNodes(-1) { }
2603       SharedPtr<IncludeInfoContext>     includeInfo;
2604       SharedPtr<InheritanceListContext> inheritsList;
2605       SharedPtr<InheritanceListContext> inheritedByList;
2606       ScopedPtr<DotClassGraph>          classGraph;
2607       ScopedPtr<DotClassGraph>          collaborationGraph;
2608       SharedPtr<TemplateList>           classes;
2609       SharedPtr<TemplateList>           innerClasses;
2610       SharedPtr<MemberListInfoContext>  publicTypes;
2611       SharedPtr<MemberListInfoContext>  publicMethods;
2612       SharedPtr<MemberListInfoContext>  publicStaticMethods;
2613       SharedPtr<MemberListInfoContext>  publicAttributes;
2614       SharedPtr<MemberListInfoContext>  publicStaticAttributes;
2615       SharedPtr<MemberListInfoContext>  publicSlots;
2616       SharedPtr<MemberListInfoContext>  protectedTypes;
2617       SharedPtr<MemberListInfoContext>  protectedMethods;
2618       SharedPtr<MemberListInfoContext>  protectedStaticMethods;
2619       SharedPtr<MemberListInfoContext>  protectedAttributes;
2620       SharedPtr<MemberListInfoContext>  protectedStaticAttributes;
2621       SharedPtr<MemberListInfoContext>  protectedSlots;
2622       SharedPtr<MemberListInfoContext>  privateTypes;
2623       SharedPtr<MemberListInfoContext>  privateMethods;
2624       SharedPtr<MemberListInfoContext>  privateStaticMethods;
2625       SharedPtr<MemberListInfoContext>  privateAttributes;
2626       SharedPtr<MemberListInfoContext>  privateStaticAttributes;
2627       SharedPtr<MemberListInfoContext>  privateSlots;
2628       SharedPtr<MemberListInfoContext>  packageTypes;
2629       SharedPtr<MemberListInfoContext>  packageMethods;
2630       SharedPtr<MemberListInfoContext>  packageStaticMethods;
2631       SharedPtr<MemberListInfoContext>  packageAttributes;
2632       SharedPtr<MemberListInfoContext>  packageStaticAttributes;
2633       SharedPtr<MemberListInfoContext>  unoIDLServices;
2634       SharedPtr<MemberListInfoContext>  unoIDLInterfaces;
2635       SharedPtr<MemberListInfoContext>  signals;
2636       SharedPtr<MemberListInfoContext>  properties;
2637       SharedPtr<MemberListInfoContext>  events;
2638       SharedPtr<MemberListInfoContext>  friends;
2639       SharedPtr<MemberListInfoContext>  related;
2640       SharedPtr<MemberListInfoContext>  detailedTypedefs;
2641       SharedPtr<MemberListInfoContext>  detailedEnums;
2642       SharedPtr<MemberListInfoContext>  detailedServices;
2643       SharedPtr<MemberListInfoContext>  detailedInterfaces;
2644       SharedPtr<MemberListInfoContext>  detailedConstructors;
2645       SharedPtr<MemberListInfoContext>  detailedMethods;
2646       SharedPtr<MemberListInfoContext>  detailedRelated;
2647       SharedPtr<MemberListInfoContext>  detailedVariables;
2648       SharedPtr<MemberListInfoContext>  detailedProperties;
2649       SharedPtr<MemberListInfoContext>  detailedEvents;
2650       SharedPtr<MemberGroupListContext> memberGroups;
2651       SharedPtr<AllMembersListContext>  allMembersList;
2652       SharedPtr<ArgumentListContext>    typeConstraints;
2653       SharedPtr<TemplateList>           examples;
2654       SharedPtr<TemplateList>           templateDecls;
2655       SharedPtr<InheritedMemberInfoListContext> additionalInheritedMembers;
2656       SharedPtr<MemberListContext>      members;
2657       SharedPtr<UsedFilesContext>       usedFiles;
2658       SharedPtr<TemplateList>           exampleList;
2659       SharedPtr<ClassContext>           categoryOf;
2660       int                               inheritanceNodes;
2661       MemberList                        allMembers;
2662     };
2663     Cachable &getCache() const
2664     {
2665       Cachable *c = static_cast<Cachable*>(m_classDef->cookie());
2666       assert(c!=0);
2667       return *c;
2668     }
2669     static PropertyMapper<ClassContext::Private> s_inst;
2670 };
2671 //%% }
2672
2673 PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst;
2674
2675 ClassContext::ClassContext(ClassDef *cd) : RefCountedContext("ClassContext")
2676 {
2677   //printf("ClassContext::ClassContext(%s)\n",cd?cd->name().data():"<none>");
2678   p = new Private(cd);
2679 }
2680
2681 ClassContext::~ClassContext()
2682 {
2683   delete p;
2684 }
2685
2686 TemplateVariant ClassContext::get(const char *n) const
2687 {
2688   return p->get(n);
2689 }
2690
2691 //------------------------------------------------------------------------
2692
2693 //%% struct Namespace(Symbol): namespace information
2694 //%% {
2695 class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private>
2696 {
2697   public:
2698     Private(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd),
2699                                 m_namespaceDef(nd)
2700     {
2701       static bool init=FALSE;
2702       if (!init)
2703       {
2704         addBaseProperties(s_inst);
2705         s_inst.addProperty("title",                &Private::title);
2706         s_inst.addProperty("highlight",            &Private::highlight);
2707         s_inst.addProperty("subhighlight",         &Private::subHighlight);
2708         s_inst.addProperty("compoundType",         &Private::compoundType);
2709         s_inst.addProperty("hasDetails",           &Private::hasDetails);
2710         s_inst.addProperty("classes",              &Private::classes);
2711         //s_inst.addProperty("interfaces",           &Private::interfaces);
2712         s_inst.addProperty("namespaces",           &Private::namespaces);
2713         s_inst.addProperty("constantgroups",       &Private::constantgroups);
2714         s_inst.addProperty("typedefs",             &Private::typedefs);
2715         s_inst.addProperty("sequences",            &Private::sequences);
2716         s_inst.addProperty("dictionaries",         &Private::dictionaries);
2717         s_inst.addProperty("enums",                &Private::enums);
2718         s_inst.addProperty("functions",            &Private::functions);
2719         s_inst.addProperty("variables",            &Private::variables);
2720         s_inst.addProperty("memberGroups",         &Private::memberGroups);
2721         s_inst.addProperty("detailedTypedefs",     &Private::detailedTypedefs);
2722         s_inst.addProperty("detailedSequences",    &Private::detailedSequences);
2723         s_inst.addProperty("detailedDictionaries", &Private::detailedDictionaries);
2724         s_inst.addProperty("detailedEnums",        &Private::detailedEnums);
2725         s_inst.addProperty("detailedFunctions",    &Private::detailedFunctions);
2726         s_inst.addProperty("detailedVariables",    &Private::detailedVariables);
2727         s_inst.addProperty("inlineClasses",        &Private::inlineClasses);
2728         init=TRUE;
2729       }
2730       if (!nd->cookie()) { nd->setCookie(new NamespaceContext::Private::Cachable(nd)); }
2731     }
2732     virtual ~Private() {}
2733     TemplateVariant get(const char *n) const
2734     {
2735       return s_inst.get(this,n);
2736     }
2737     TemplateVariant title() const
2738     {
2739       return TemplateVariant(m_namespaceDef->title());
2740     }
2741     TemplateVariant highlight() const
2742     {
2743       return TemplateVariant("namespaces");
2744     }
2745     TemplateVariant subHighlight() const
2746     {
2747       return TemplateVariant("");
2748     }
2749     TemplateVariant compoundType() const
2750     {
2751       return m_namespaceDef->compoundTypeString();
2752     }
2753     TemplateVariant hasDetails() const
2754     {
2755       return m_namespaceDef->hasDetailedDescription();
2756     }
2757     TemplateVariant classes() const
2758     {
2759       Cachable &cache = getCache();
2760       if (!cache.classes)
2761       {
2762         static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2763         TemplateList *classList = TemplateList::alloc();
2764         if (m_namespaceDef->getClassSDict())
2765         {
2766           ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict());
2767           ClassDef *cd;
2768           for (sdi.toFirst();(cd=sdi.current());++sdi)
2769           {
2770             if (sliceOpt && (cd->compoundType()==ClassDef::Struct    ||
2771                              cd->compoundType()==ClassDef::Interface ||
2772                              cd->compoundType()==ClassDef::Exception))
2773             {
2774               continue; // These types appear in their own sections.
2775             }
2776             if (cd->visibleInParentsDeclList())
2777             {
2778               classList->append(ClassContext::alloc(cd));
2779             }
2780           }
2781         }
2782         cache.classes.reset(classList);
2783       }
2784       return cache.classes.get();
2785     }
2786     TemplateVariant namespaces() const
2787     {
2788       Cachable &cache = getCache();
2789       if (!cache.namespaces)
2790       {
2791         TemplateList *namespaceList = TemplateList::alloc();
2792         if (m_namespaceDef->getNamespaceSDict())
2793         {
2794           NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict());
2795           NamespaceDef *nd;
2796           for (sdi.toFirst();(nd=sdi.current());++sdi)
2797           {
2798             if (nd->isLinkable() && !nd->isConstantGroup())
2799             {
2800               namespaceList->append(NamespaceContext::alloc(nd));
2801             }
2802           }
2803         }
2804         cache.namespaces.reset(namespaceList);
2805       }
2806       return cache.namespaces.get();
2807     }
2808     TemplateVariant constantgroups() const
2809     {
2810       Cachable &cache = getCache();
2811       if (!cache.constantgroups)
2812       {
2813         TemplateList *namespaceList = TemplateList::alloc();
2814         if (m_namespaceDef->getNamespaceSDict())
2815         {
2816           NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict());
2817           NamespaceDef *nd;
2818           for (sdi.toFirst();(nd=sdi.current());++sdi)
2819           {
2820             if (nd->isLinkable() && nd->isConstantGroup())
2821             {
2822               namespaceList->append(NamespaceContext::alloc(nd));
2823             }
2824           }
2825         }
2826         cache.constantgroups.reset(namespaceList);
2827       }
2828       return cache.constantgroups.get();
2829     }
2830     TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
2831                                   MemberListType type,const char *title,bool detailed=FALSE) const
2832     {
2833       if (!list)
2834       {
2835         MemberList *ml = m_namespaceDef->getMemberList(type);
2836         if (ml)
2837         {
2838           list.reset(MemberListInfoContext::alloc(m_namespaceDef,relPathAsString(),ml,title,""));
2839         }
2840       }
2841       if (list)
2842       {
2843         return list.get();
2844       }
2845       else
2846       {
2847         return TemplateVariant(FALSE);
2848       }
2849     }
2850     TemplateVariant typedefs() const
2851     {
2852       return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
2853     }
2854     TemplateVariant sequences() const
2855     {
2856       return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
2857     }
2858     TemplateVariant dictionaries() const
2859     {
2860       return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
2861     }
2862     TemplateVariant enums() const
2863     {
2864       return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
2865     }
2866     TemplateVariant functions() const
2867     {
2868       QCString title = theTranslator->trFunctions();
2869       SrcLangExt lang = m_namespaceDef->getLanguage();
2870       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
2871       else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
2872       return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
2873     }
2874     TemplateVariant variables() const
2875     {
2876       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2877       return getMemberList(getCache().variables,MemberListType_decVarMembers,
2878                            sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
2879     }
2880     TemplateVariant memberGroups() const
2881     {
2882       Cachable &cache = getCache();
2883       if (!cache.memberGroups)
2884       {
2885         if (m_namespaceDef->getMemberGroupSDict())
2886         {
2887           cache.memberGroups.reset(MemberGroupListContext::alloc(m_namespaceDef,relPathAsString(),m_namespaceDef->getMemberGroupSDict(),m_namespaceDef->subGrouping()));
2888         }
2889         else
2890         {
2891           cache.memberGroups.reset(MemberGroupListContext::alloc());
2892         }
2893       }
2894       return cache.memberGroups.get();
2895     }
2896     TemplateVariant detailedTypedefs() const
2897     {
2898       return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
2899     }
2900     TemplateVariant detailedSequences() const
2901     {
2902       return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
2903     }
2904     TemplateVariant detailedDictionaries() const
2905     {
2906       return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
2907     }
2908     TemplateVariant detailedEnums() const
2909     {
2910       return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
2911     }
2912     TemplateVariant detailedFunctions() const
2913     {
2914       QCString title = theTranslator->trFunctionDocumentation();
2915       SrcLangExt lang = m_namespaceDef->getLanguage();
2916       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
2917       return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
2918     }
2919     TemplateVariant detailedVariables() const
2920     {
2921       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2922       return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,
2923                            sliceOpt ? theTranslator->trConstantDocumentation() :
2924                            theTranslator->trVariableDocumentation());
2925     }
2926     TemplateVariant inlineClasses() const
2927     {
2928       Cachable &cache = getCache();
2929       if (!cache.inlineClasses)
2930       {
2931         TemplateList *classList = TemplateList::alloc();
2932         if (m_namespaceDef->getClassSDict())
2933         {
2934           ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict());
2935           ClassDef *cd;
2936           for (sdi.toFirst();(cd=sdi.current());++sdi)
2937           {
2938             if (cd->name().find('@')==-1 &&
2939                 cd->isLinkableInProject() &&
2940                 cd->isEmbeddedInOuterScope() &&
2941                 cd->partOfGroups()==0)
2942             {
2943               classList->append(ClassContext::alloc(cd));
2944             }
2945           }
2946         }
2947         cache.inlineClasses.reset(classList);
2948       }
2949       return cache.inlineClasses.get();
2950     }
2951   private:
2952     NamespaceDef *m_namespaceDef;
2953     struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable
2954     {
2955       Cachable(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {}
2956       SharedPtr<TemplateList>               classes;
2957       SharedPtr<TemplateList>               interfaces;
2958       SharedPtr<TemplateList>               namespaces;
2959       SharedPtr<TemplateList>               constantgroups;
2960       SharedPtr<MemberListInfoContext>      typedefs;
2961       SharedPtr<MemberListInfoContext>      sequences;
2962       SharedPtr<MemberListInfoContext>      dictionaries;
2963       SharedPtr<MemberListInfoContext>      enums;
2964       SharedPtr<MemberListInfoContext>      functions;
2965       SharedPtr<MemberListInfoContext>      variables;
2966       SharedPtr<MemberGroupListContext>     memberGroups;
2967       SharedPtr<MemberListInfoContext>      detailedTypedefs;
2968       SharedPtr<MemberListInfoContext>      detailedSequences;
2969       SharedPtr<MemberListInfoContext>      detailedDictionaries;
2970       SharedPtr<MemberListInfoContext>      detailedEnums;
2971       SharedPtr<MemberListInfoContext>      detailedFunctions;
2972       SharedPtr<MemberListInfoContext>      detailedVariables;
2973       SharedPtr<TemplateList>               inlineClasses;
2974     };
2975     Cachable &getCache() const
2976     {
2977       Cachable *c = static_cast<Cachable*>(m_namespaceDef->cookie());
2978       assert(c!=0);
2979       return *c;
2980     }
2981     static PropertyMapper<NamespaceContext::Private> s_inst;
2982 };
2983 //%% }
2984
2985 PropertyMapper<NamespaceContext::Private> NamespaceContext::Private::s_inst;
2986
2987 NamespaceContext::NamespaceContext(NamespaceDef *nd) : RefCountedContext("NamespaceContext")
2988 {
2989   p = new Private(nd);
2990 }
2991
2992 NamespaceContext::~NamespaceContext()
2993 {
2994   delete p;
2995 }
2996
2997 TemplateVariant NamespaceContext::get(const char *n) const
2998 {
2999   return p->get(n);
3000 }
3001
3002 //------------------------------------------------------------------------
3003
3004 //%% struct File(Symbol): file information
3005 //%% {
3006 class FileContext::Private : public DefinitionContext<FileContext::Private>
3007 {
3008   public:
3009     Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
3010     {
3011       if (fd==0) abort();
3012       static bool init=FALSE;
3013       if (!init)
3014       {
3015         addBaseProperties(s_inst);
3016         s_inst.addProperty("title",                     &Private::title);
3017         s_inst.addProperty("highlight",                 &Private::highlight);
3018         s_inst.addProperty("subhighlight",              &Private::subHighlight);
3019         s_inst.addProperty("versionInfo",               &Private::versionInfo);
3020         s_inst.addProperty("includeList",               &Private::includeList);
3021         s_inst.addProperty("hasIncludeGraph",           &Private::hasIncludeGraph);
3022         s_inst.addProperty("hasIncludedByGraph",        &Private::hasIncludedByGraph);
3023         s_inst.addProperty("includeGraph",              &Private::includeGraph);
3024         s_inst.addProperty("includedByGraph",           &Private::includedByGraph);
3025         s_inst.addProperty("hasDetails",                &Private::hasDetails);
3026         s_inst.addProperty("hasSourceFile",             &Private::hasSourceFile);
3027         s_inst.addProperty("sources",                   &Private::sources);
3028         s_inst.addProperty("version",                   &Private::version);
3029         s_inst.addProperty("classes",                   &Private::classes);
3030         s_inst.addProperty("namespaces",                &Private::namespaces);
3031         s_inst.addProperty("constantgroups",            &Private::constantgroups);
3032         s_inst.addProperty("macros",                    &Private::macros);
3033         s_inst.addProperty("typedefs",                  &Private::typedefs);
3034         s_inst.addProperty("sequences",                 &Private::sequences);
3035         s_inst.addProperty("dictionaries",              &Private::dictionaries);
3036         s_inst.addProperty("enums",                     &Private::enums);
3037         s_inst.addProperty("functions",                 &Private::functions);
3038         s_inst.addProperty("variables",                 &Private::variables);
3039         s_inst.addProperty("memberGroups",              &Private::memberGroups);
3040         s_inst.addProperty("detailedMacros",            &Private::detailedMacros);
3041         s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
3042         s_inst.addProperty("detailedSequences",         &Private::detailedSequences);
3043         s_inst.addProperty("detailedDictionaries",      &Private::detailedDictionaries);
3044         s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
3045         s_inst.addProperty("detailedFunctions",         &Private::detailedFunctions);
3046         s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
3047         s_inst.addProperty("inlineClasses",             &Private::inlineClasses);
3048         s_inst.addProperty("compoundType",              &Private::compoundType);
3049         init=TRUE;
3050       }
3051       if (!fd->cookie()) { fd->setCookie(new FileContext::Private::Cachable(fd)); }
3052     }
3053     virtual ~Private() {}
3054     TemplateVariant get(const char *n) const
3055     {
3056       return s_inst.get(this,n);
3057     }
3058     TemplateVariant title() const
3059     {
3060       return m_fileDef->title();
3061     }
3062     TemplateVariant highlight() const
3063     {
3064       return TemplateVariant("files");
3065     }
3066     TemplateVariant subHighlight() const
3067     {
3068       return TemplateVariant("");
3069     }
3070     TemplateVariant versionInfo() const
3071     {
3072       return m_fileDef->getVersion();
3073     }
3074     TemplateVariant includeList() const
3075     {
3076       Cachable &cache = getCache();
3077       if (!cache.includeInfoList && m_fileDef->includeFileList())
3078       {
3079         cache.includeInfoList.reset(IncludeInfoListContext::alloc(
3080               *m_fileDef->includeFileList(),m_fileDef->getLanguage()));
3081       }
3082       if (cache.includeInfoList)
3083       {
3084         return cache.includeInfoList.get();
3085       }
3086       else
3087       {
3088         return TemplateVariant(FALSE);
3089       }
3090     }
3091     DotInclDepGraph *getIncludeGraph() const
3092     {
3093       Cachable &cache = getCache();
3094       if (!cache.includeGraph)
3095       {
3096         cache.includeGraph.reset(new DotInclDepGraph(m_fileDef,FALSE));
3097       }
3098       return cache.includeGraph.get();
3099     }
3100     TemplateVariant hasIncludeGraph() const
3101     {
3102       static bool haveDot = Config_getBool(HAVE_DOT);
3103       DotInclDepGraph *incGraph = getIncludeGraph();
3104       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
3105     }
3106     TemplateVariant includeGraph() const
3107     {
3108       static bool haveDot = Config_getBool(HAVE_DOT);
3109       QGString result;
3110       if (haveDot)
3111       {
3112         DotInclDepGraph *cg = getIncludeGraph();
3113         FTextStream t(&result);
3114         switch (g_globals.outputFormat)
3115         {
3116           case ContextOutputFormat_Html:
3117             {
3118               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
3119                   g_globals.outputDir,
3120                   g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
3121                   relPathAsString(),TRUE,g_globals.dynSectionId
3122                   );
3123             }
3124             break;
3125           case ContextOutputFormat_Latex:
3126             {
3127               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
3128                   g_globals.outputDir,
3129                   g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
3130                   relPathAsString(),TRUE,g_globals.dynSectionId
3131                   );
3132             }
3133             break;
3134             // TODO: support other generators
3135           default:
3136             err("context.cpp: output format not yet supported");
3137             break;
3138         }
3139         g_globals.dynSectionId++;
3140       }
3141       return TemplateVariant(result.data(),TRUE);
3142     }
3143     DotInclDepGraph *getIncludedByGraph() const
3144     {
3145       Cachable &cache = getCache();
3146       if (!cache.includedByGraph)
3147       {
3148         cache.includedByGraph.reset(new DotInclDepGraph(m_fileDef,TRUE));
3149       }
3150       return cache.includedByGraph.get();
3151     }
3152     TemplateVariant hasIncludedByGraph() const
3153     {
3154       static bool haveDot = Config_getBool(HAVE_DOT);
3155       DotInclDepGraph *incGraph = getIncludedByGraph();
3156       return (haveDot && !incGraph->isTooBig() && !incGraph->isTrivial());
3157     }
3158     TemplateVariant includedByGraph() const
3159     {
3160       static bool haveDot = Config_getBool(HAVE_DOT);
3161       QGString result;
3162       if (haveDot)
3163       {
3164         DotInclDepGraph *cg = getIncludedByGraph();
3165         FTextStream t(&result);
3166         switch (g_globals.outputFormat)
3167         {
3168           case ContextOutputFormat_Html:
3169             {
3170               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
3171                   g_globals.outputDir,
3172                   g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
3173                   relPathAsString(),TRUE,g_globals.dynSectionId
3174                   );
3175             }
3176             break;
3177           case ContextOutputFormat_Latex:
3178             {
3179               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
3180                   g_globals.outputDir,
3181                   g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
3182                   relPathAsString(),TRUE,g_globals.dynSectionId
3183                   );
3184             }
3185             break;
3186             // TODO: support other generators
3187           default:
3188             err("context.cpp: output format not yet supported");
3189             break;
3190         }
3191         g_globals.dynSectionId++;
3192       }
3193       return TemplateVariant(result.data(),TRUE);
3194     }
3195     TemplateVariant hasDetails() const
3196     {
3197       return m_fileDef->hasDetailedDescription();
3198     }
3199     TemplateVariant hasSourceFile() const
3200     {
3201       return m_fileDef->generateSourceFile();
3202     }
3203     TemplateVariant sources() const
3204     {
3205       Cachable &cache = getCache();
3206       if (!cache.sources)
3207       {
3208         if (m_fileDef->generateSourceFile())
3209         {
3210           cache.sources.reset(new TemplateVariant(parseCode(m_fileDef,relPathAsString())));
3211         }
3212         else
3213         {
3214           cache.sources.reset(new TemplateVariant(""));
3215         }
3216       }
3217       return *cache.sources;
3218     }
3219     TemplateVariant version() const
3220     {
3221       return m_fileDef->fileVersion();
3222     }
3223     TemplateVariant classes() const
3224     {
3225       Cachable &cache = getCache();
3226       if (!cache.classes)
3227       {
3228         TemplateList *classList = TemplateList::alloc();
3229         if (m_fileDef->getClassSDict())
3230         {
3231           ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
3232           ClassDef *cd;
3233           for (sdi.toFirst();(cd=sdi.current());++sdi)
3234           {
3235             if (cd->visibleInParentsDeclList())
3236             {
3237               classList->append(ClassContext::alloc(cd));
3238             }
3239           }
3240         }
3241         cache.classes.reset(classList);
3242       }
3243       return cache.classes.get();
3244     }
3245     TemplateVariant namespaces() const
3246     {
3247       Cachable &cache = getCache();
3248       if (!cache.namespaces)
3249       {
3250         TemplateList *namespaceList = TemplateList::alloc();
3251         if (m_fileDef->getNamespaceSDict())
3252         {
3253           NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict());
3254           NamespaceDef *nd;
3255           for (sdi.toFirst();(nd=sdi.current());++sdi)
3256           {
3257             if (nd->isLinkable() && !nd->isConstantGroup())
3258             {
3259               namespaceList->append(NamespaceContext::alloc(nd));
3260             }
3261           }
3262         }
3263         cache.namespaces.reset(namespaceList);
3264       }
3265       return cache.namespaces.get();
3266     }
3267     TemplateVariant constantgroups() const
3268     {
3269       Cachable &cache = getCache();
3270       if (!cache.constantgroups)
3271       {
3272         TemplateList *namespaceList = TemplateList::alloc();
3273         if (m_fileDef->getNamespaceSDict())
3274         {
3275           NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict());
3276           NamespaceDef *nd;
3277           for (sdi.toFirst();(nd=sdi.current());++sdi)
3278           {
3279             if (nd->isLinkable() && nd->isConstantGroup())
3280             {
3281               namespaceList->append(NamespaceContext::alloc(nd));
3282             }
3283           }
3284         }
3285         cache.constantgroups.reset(namespaceList);
3286       }
3287       return cache.constantgroups.get();
3288     }
3289     TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
3290                                   MemberListType type,const char *title,bool detailed=FALSE) const
3291     {
3292       if (!list)
3293       {
3294         MemberList *ml = m_fileDef->getMemberList(type);
3295         if (ml)
3296         {
3297           list.reset(MemberListInfoContext::alloc(m_fileDef,relPathAsString(),ml,title,""));
3298         }
3299       }
3300       if (list)
3301       {
3302         return list.get();
3303       }
3304       else
3305       {
3306         return TemplateVariant(FALSE);
3307       }
3308     }
3309     TemplateVariant macros() const
3310     {
3311       return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines());
3312     }
3313     TemplateVariant typedefs() const
3314     {
3315       return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
3316     }
3317     TemplateVariant sequences() const
3318     {
3319       return getMemberList(getCache().sequences,MemberListType_decSequenceMembers,theTranslator->trSequences());
3320     }
3321     TemplateVariant dictionaries() const
3322     {
3323       return getMemberList(getCache().dictionaries,MemberListType_decDictionaryMembers,theTranslator->trDictionaries());
3324     }
3325     TemplateVariant enums() const
3326     {
3327       return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
3328     }
3329     TemplateVariant functions() const
3330     {
3331       QCString title = theTranslator->trFunctions();
3332       SrcLangExt lang = m_fileDef->getLanguage();
3333       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
3334       else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
3335       return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
3336     }
3337     TemplateVariant variables() const
3338     {
3339       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
3340       return getMemberList(getCache().variables,MemberListType_decVarMembers,
3341                            sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
3342     }
3343     TemplateVariant memberGroups() const
3344     {
3345       Cachable &cache = getCache();
3346       if (!cache.memberGroups)
3347       {
3348         if (m_fileDef->getMemberGroupSDict())
3349         {
3350           cache.memberGroups.reset(MemberGroupListContext::alloc(m_fileDef,relPathAsString(),m_fileDef->getMemberGroupSDict(),m_fileDef->subGrouping()));
3351         }
3352         else
3353         {
3354           cache.memberGroups.reset(MemberGroupListContext::alloc());
3355         }
3356       }
3357       return cache.memberGroups.get();
3358     }
3359     TemplateVariant detailedMacros() const
3360     {
3361       return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
3362     }
3363     TemplateVariant detailedTypedefs() const
3364     {
3365       return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
3366     }
3367     TemplateVariant detailedSequences() const
3368     {
3369       return getMemberList(getCache().detailedSequences,MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation());
3370     }
3371     TemplateVariant detailedDictionaries() const
3372     {
3373       return getMemberList(getCache().detailedDictionaries,MemberListType_docDictionaryMembers,theTranslator->trDictionaryDocumentation());
3374     }
3375     TemplateVariant detailedEnums() const
3376     {
3377       return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
3378     }
3379     TemplateVariant detailedFunctions() const
3380     {
3381       QCString title = theTranslator->trFunctionDocumentation();
3382       SrcLangExt lang = m_fileDef->getLanguage();
3383       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
3384       return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
3385     }
3386     TemplateVariant detailedVariables() const
3387     {
3388       return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
3389     }
3390     TemplateVariant inlineClasses() const
3391     {
3392       Cachable &cache = getCache();
3393       if (!cache.inlineClasses)
3394       {
3395         TemplateList *classList = TemplateList::alloc();
3396         if (m_fileDef->getClassSDict())
3397         {
3398           ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
3399           ClassDef *cd;
3400           for (sdi.toFirst();(cd=sdi.current());++sdi)
3401           {
3402             if (cd->name().find('@')==-1 &&
3403                 cd->isLinkableInProject() &&
3404                 cd->isEmbeddedInOuterScope() &&
3405                 cd->partOfGroups()==0)
3406             {
3407               classList->append(ClassContext::alloc(cd));
3408             }
3409           }
3410         }
3411         cache.inlineClasses.reset(classList);
3412       }
3413       return cache.inlineClasses.get();
3414     }
3415     TemplateVariant compoundType() const
3416     {
3417       return theTranslator->trFile(FALSE,TRUE);
3418     }
3419
3420   private:
3421     FileDef *m_fileDef;
3422     struct Cachable : public DefinitionContext<FileContext::Private>::Cachable
3423     {
3424       Cachable(FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {}
3425       SharedPtr<IncludeInfoListContext>     includeInfoList;
3426       ScopedPtr<DotInclDepGraph>            includeGraph;
3427       ScopedPtr<DotInclDepGraph>            includedByGraph;
3428       ScopedPtr<TemplateVariant>            sources;
3429       SharedPtr<TemplateList>               classes;
3430       SharedPtr<TemplateList>               namespaces;
3431       SharedPtr<TemplateList>               constantgroups;
3432       SharedPtr<MemberListInfoContext>      macros;
3433       SharedPtr<MemberListInfoContext>      typedefs;
3434       SharedPtr<MemberListInfoContext>      sequences;
3435       SharedPtr<MemberListInfoContext>      dictionaries;
3436       SharedPtr<MemberListInfoContext>      enums;
3437       SharedPtr<MemberListInfoContext>      functions;
3438       SharedPtr<MemberListInfoContext>      variables;
3439       SharedPtr<MemberGroupListContext>     memberGroups;
3440       SharedPtr<MemberListInfoContext>      detailedMacros;
3441       SharedPtr<MemberListInfoContext>      detailedTypedefs;
3442       SharedPtr<MemberListInfoContext>      detailedSequences;
3443       SharedPtr<MemberListInfoContext>      detailedDictionaries;
3444       SharedPtr<MemberListInfoContext>      detailedEnums;
3445       SharedPtr<MemberListInfoContext>      detailedFunctions;
3446       SharedPtr<MemberListInfoContext>      detailedVariables;
3447       SharedPtr<TemplateList>               inlineClasses;
3448     };
3449     Cachable &getCache() const
3450     {
3451       Cachable *c = static_cast<Cachable*>(m_fileDef->cookie());
3452       assert(c!=0);
3453       return *c;
3454     }
3455     static PropertyMapper<FileContext::Private> s_inst;
3456 };
3457 //%% }
3458
3459 PropertyMapper<FileContext::Private> FileContext::Private::s_inst;
3460
3461 FileContext::FileContext(FileDef *fd) : RefCountedContext("FileContext")
3462 {
3463   p = new Private(fd);
3464 }
3465
3466 FileContext::~FileContext()
3467 {
3468   delete p;
3469 }
3470
3471 TemplateVariant FileContext::get(const char *n) const
3472 {
3473   return p->get(n);
3474 }
3475
3476 //------------------------------------------------------------------------
3477
3478 //%% struct Dir(Symbol): directory information
3479 //%% {
3480 class DirContext::Private : public DefinitionContext<DirContext::Private>
3481 {
3482   public:
3483     Private(DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd)
3484     {
3485       static bool init=FALSE;
3486       if (!init)
3487       {
3488         addBaseProperties(s_inst);
3489         s_inst.addProperty("title",         &Private::title);
3490         s_inst.addProperty("highlight",     &Private::highlight);
3491         s_inst.addProperty("subhighlight",  &Private::subHighlight);
3492         s_inst.addProperty("dirName",       &Private::dirName);
3493         s_inst.addProperty("dirs",          &Private::dirs);
3494         s_inst.addProperty("files",         &Private::files);
3495         s_inst.addProperty("hasDetails",    &Private::hasDetails);
3496         s_inst.addProperty("hasDirGraph",   &Private::hasDirGraph);
3497         s_inst.addProperty("dirGraph",      &Private::dirGraph);
3498         s_inst.addProperty("compoundType",  &Private::compoundType);
3499         init=TRUE;
3500       }
3501       if (!dd->cookie()) { dd->setCookie(new DirContext::Private::Cachable(dd)); }
3502     }
3503     virtual ~Private() {}
3504     TemplateVariant get(const char *n) const
3505     {
3506       return s_inst.get(this,n);
3507     }
3508     TemplateVariant title() const
3509     {
3510       return TemplateVariant(m_dirDef->shortTitle());
3511     }
3512     TemplateVariant highlight() const
3513     {
3514       return TemplateVariant("files");
3515     }
3516     TemplateVariant subHighlight() const
3517     {
3518       return TemplateVariant("");
3519     }
3520     TemplateVariant dirName() const
3521     {
3522       return TemplateVariant(m_dirDef->shortName());
3523     }
3524     TemplateVariant dirs() const
3525     {
3526       Cachable &cache = getCache();
3527       if (!cache.dirs)
3528       {
3529         cache.dirs.reset(TemplateList::alloc());
3530         const DirList &subDirs = m_dirDef->subDirs();
3531         QListIterator<DirDef> it(subDirs);
3532         DirDef *dd;
3533         for (it.toFirst();(dd=it.current());++it)
3534         {
3535           DirContext *dc = new DirContext(dd);
3536           cache.dirs->append(dc);
3537         }
3538       }
3539       return cache.dirs.get();
3540     }
3541     TemplateVariant files() const
3542     {
3543       Cachable &cache = getCache();
3544       if (!cache.files)
3545       {
3546         cache.files.reset(TemplateList::alloc());
3547         FileList *files = m_dirDef->getFiles();
3548         if (files)
3549         {
3550           QListIterator<FileDef> it(*files);
3551           FileDef *fd;
3552           for (it.toFirst();(fd=it.current());++it)
3553           {
3554             FileContext *fc = FileContext::alloc(fd);
3555             cache.files->append(fc);
3556           }
3557         }
3558       }
3559       return cache.files.get();
3560     }
3561     TemplateVariant hasDetails() const
3562     {
3563       return m_dirDef->hasDetailedDescription();
3564     }
3565     TemplateVariant compoundType() const
3566     {
3567       return theTranslator->trDir(FALSE,TRUE);
3568     }
3569     TemplateVariant relPath() const
3570     {
3571       return "";
3572     }
3573     DotDirDeps *getDirDepsGraph() const
3574     {
3575       Cachable &cache = getCache();
3576       if (!cache.dirDepsGraph)
3577       {
3578         cache.dirDepsGraph.reset(new DotDirDeps(m_dirDef));
3579       }
3580       return cache.dirDepsGraph.get();
3581     }
3582     TemplateVariant hasDirGraph() const
3583     {
3584       bool result=FALSE;
3585       static bool haveDot  = Config_getBool(HAVE_DOT);
3586       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
3587       if (haveDot && dirGraph)
3588       {
3589         DotDirDeps *graph = getDirDepsGraph();
3590         result = !graph->isTrivial();
3591       }
3592       return result;
3593     }
3594     TemplateVariant dirGraph() const
3595     {
3596       QGString result;
3597       static bool haveDot  = Config_getBool(HAVE_DOT);
3598       static bool dirGraph = Config_getBool(DIRECTORY_GRAPH);
3599       if (haveDot && dirGraph)
3600       {
3601         DotDirDeps *graph = getDirDepsGraph();
3602         FTextStream t(&result);
3603         switch (g_globals.outputFormat)
3604         {
3605           case ContextOutputFormat_Html:
3606             {
3607               graph->writeGraph(t,GOF_BITMAP,
3608                                 EOF_Html,
3609                                 g_globals.outputDir,
3610                                 g_globals.outputDir+portable_pathSeparator()+m_dirDef->getOutputFileBase()+Doxygen::htmlFileExtension,
3611                                 relPathAsString(),
3612                                 TRUE,
3613                                 g_globals.dynSectionId,
3614                                 FALSE);
3615             }
3616             break;
3617           case ContextOutputFormat_Latex:
3618             {
3619               graph->writeGraph(t,GOF_EPS,
3620                                 EOF_LaTeX,
3621                                 g_globals.outputDir,
3622                                 g_globals.outputDir+portable_pathSeparator()+m_dirDef->getOutputFileBase()+".tex",
3623                                 relPathAsString(),
3624                                 TRUE,
3625                                 g_globals.dynSectionId,
3626                                 FALSE);
3627             }
3628             break;
3629             // TODO: support other generators
3630           default:
3631             err("context.cpp: output format not yet supported");
3632             break;
3633         }
3634         g_globals.dynSectionId++;
3635       }
3636       return TemplateVariant(result.data(),TRUE);
3637     }
3638
3639   private:
3640     DirDef *m_dirDef;
3641     struct Cachable : public DefinitionContext<DirContext::Private>::Cachable
3642     {
3643       Cachable(DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {}
3644       SharedPtr<TemplateList>  dirs;
3645       SharedPtr<TemplateList>  files;
3646       ScopedPtr<DotDirDeps>    dirDepsGraph;
3647     };
3648     Cachable &getCache() const
3649     {
3650       Cachable *c = static_cast<Cachable*>(m_dirDef->cookie());
3651       assert(c!=0);
3652       return *c;
3653     }
3654     static PropertyMapper<DirContext::Private> s_inst;
3655 };
3656 //%% }
3657
3658 PropertyMapper<DirContext::Private> DirContext::Private::s_inst;
3659
3660 DirContext::DirContext(DirDef *fd) : RefCountedContext("DirContext")
3661 {
3662   p = new Private(fd);
3663 }
3664
3665 DirContext::~DirContext()
3666 {
3667   delete p;
3668 }
3669
3670 TemplateVariant DirContext::get(const char *n) const
3671 {
3672   return p->get(n);
3673 }
3674
3675 //------------------------------------------------------------------------
3676
3677 //%% struct Page(Symbol): page information
3678 //%% {
3679 class PageContext::Private : public DefinitionContext<PageContext::Private>
3680 {
3681   public:
3682     Private(PageDef *pd,bool isMainPage,bool isExample)
3683       : DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage),
3684         m_isExample(isExample)
3685     {
3686       static bool init=FALSE;
3687       if (!init)
3688       {
3689         addBaseProperties(s_inst);
3690         s_inst.addProperty("title",       &Private::title);
3691         s_inst.addProperty("highlight",   &Private::highlight);
3692         s_inst.addProperty("subhighlight",&Private::subHighlight);
3693         s_inst.addProperty("example",     &Private::example);
3694         init=TRUE;
3695       }
3696       if (!pd->cookie()) { pd->setCookie(new PageContext::Private::Cachable(pd)); }
3697     }
3698     virtual ~Private() {}
3699     TemplateVariant get(const char *n) const
3700     {
3701       return s_inst.get(this,n);
3702     }
3703     TemplateVariant title() const
3704     {
3705       if (m_isMainPage)
3706       {
3707         if (mainPageHasTitle())
3708         {
3709           return m_pageDef->title();
3710         }
3711         else
3712         {
3713           return theTranslator->trMainPage();
3714         }
3715       }
3716       else if (m_isExample)
3717       {
3718         return m_pageDef->name();
3719       }
3720       else
3721       {
3722         return m_pageDef->title();
3723       }
3724     }
3725     TemplateVariant relPath() const
3726     {
3727       if (m_isMainPage)
3728       {
3729         return "";
3730       }
3731       else
3732       {
3733         return DefinitionContext<PageContext::Private>::relPath();
3734       }
3735     }
3736     TemplateVariant highlight() const
3737     {
3738       if (m_isMainPage)
3739       {
3740         return "main";
3741       }
3742       else
3743       {
3744         return "pages";
3745       }
3746     }
3747     TemplateVariant subHighlight() const
3748     {
3749       return "";
3750     }
3751     TemplateVariant example() const
3752     {
3753       if (m_isExample)
3754       {
3755         Cachable &cache = getCache();
3756         if (!cache.example || g_globals.outputFormat!=cache.exampleOutputFormat)
3757         {
3758           cache.example.reset(new TemplateVariant(
3759                 parseDoc(m_pageDef,m_pageDef->docFile(),m_pageDef->docLine(),
3760                   relPathAsString(),"\\include "+m_pageDef->name(),FALSE)));
3761           cache.exampleOutputFormat = g_globals.outputFormat;
3762         }
3763         return *cache.example;
3764       }
3765       else
3766       {
3767         return TemplateVariant("");
3768       }
3769     }
3770   private:
3771     PageDef *m_pageDef;
3772     struct Cachable : public DefinitionContext<PageContext::Private>::Cachable
3773     {
3774       Cachable(PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd),
3775                               exampleOutputFormat(ContextOutputFormat_Unspecified) { }
3776       ScopedPtr<TemplateVariant> example;
3777       ContextOutputFormat        exampleOutputFormat;
3778     };
3779     Cachable &getCache() const
3780     {
3781       Cachable *c = static_cast<Cachable*>(m_pageDef->cookie());
3782       assert(c!=0);
3783       return *c;
3784     }
3785     bool m_isMainPage;
3786     bool m_isExample;
3787     static PropertyMapper<PageContext::Private> s_inst;
3788 };
3789 //%% }
3790
3791 PropertyMapper<PageContext::Private> PageContext::Private::s_inst;
3792
3793 PageContext::PageContext(PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext")
3794 {
3795   p = new Private(pd,isMainPage,isExample);
3796 }
3797
3798 PageContext::~PageContext()
3799 {
3800   delete p;
3801 }
3802
3803 TemplateVariant PageContext::get(const char *n) const
3804 {
3805   return p->get(n);
3806 }
3807
3808 //------------------------------------------------------------------------
3809
3810 class TextGeneratorHtml : public TextGeneratorIntf
3811 {
3812   public:
3813     TextGeneratorHtml(FTextStream &ts,const QCString &relPath)
3814        : m_ts(ts), m_relPath(relPath) {}
3815     void writeString(const char *s,bool keepSpaces) const
3816     {
3817       if (s==0) return;
3818       if (keepSpaces)
3819       {
3820         const char *p=s;
3821         char c;
3822         while ((c=*p++))
3823         {
3824           switch(c)
3825           {
3826             case '<':  m_ts << "&lt;"; break;
3827             case '>':  m_ts << "&gt;"; break;
3828             case '\'': m_ts << "&#39;"; break;
3829             case '"':  m_ts << "&quot;"; break;
3830             case '&':  m_ts << "&amp;"; break;
3831             case ' ':  m_ts << "&#160;"; break;
3832           }
3833         }
3834       }
3835       else
3836       {
3837         m_ts << convertToHtml(s);
3838       }
3839     }
3840
3841     void writeBreak(int indent) const
3842     {
3843       m_ts << "<br />";
3844       for (int i=0;i<indent;i++)
3845       {
3846         m_ts << "&#160;";
3847       }
3848     }
3849
3850     void writeLink(const char *ref,const char *f,
3851                    const char *anchor,const char *name
3852                   ) const
3853     {
3854       if (ref)
3855       {
3856         m_ts << "<a class=\"elRef\" ";
3857         m_ts << externalLinkTarget() << externalRef(m_relPath,ref,FALSE);
3858       }
3859       else
3860       {
3861         m_ts << "<a class=\"el\" ";
3862       }
3863       m_ts << "href=\"";
3864       m_ts << externalRef(m_relPath,ref,TRUE);
3865       if (f) m_ts << f << Doxygen::htmlFileExtension;
3866       if (anchor) m_ts << "#" << anchor;
3867       m_ts << "\">";
3868       m_ts << convertToHtml(name);
3869       m_ts << "</a>";
3870     }
3871
3872   private:
3873     FTextStream &m_ts;
3874     QCString m_relPath;
3875 };
3876
3877 //------------------------------------------------------------------------
3878
3879 class TextGeneratorLatex : public TextGeneratorIntf
3880 {
3881   public:
3882     TextGeneratorLatex(FTextStream &ts) : m_ts(ts) {}
3883     void writeString(const char *s,bool keepSpaces) const
3884     {
3885       if (s==0) return;
3886       m_ts << convertToLaTeX(s,FALSE,keepSpaces);
3887     }
3888     void writeBreak(int indent) const
3889     {
3890       m_ts << "\\\\*\n";
3891       for (int i=0;i<indent;i++)
3892       {
3893         m_ts << "~";
3894       }
3895     }
3896     void writeLink(const char *ref,const char *f,
3897                    const char *anchor,const char *text
3898                   ) const
3899     {
3900       static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
3901       if (!ref && pdfHyperlinks)
3902       {
3903         m_ts << "\\mbox{\\hyperlink{";
3904         if (f) m_ts << stripPath(f);
3905         if (f && anchor) m_ts << "_";
3906         if (anchor) m_ts << anchor;
3907         m_ts << "}{";
3908         filterLatexString(m_ts,text);
3909         m_ts << "}}";
3910       }
3911       else
3912       {
3913         m_ts << "\\textbf{ ";
3914         filterLatexString(m_ts,text);
3915         m_ts << "}";
3916       }
3917     }
3918
3919   private:
3920     FTextStream &m_ts;
3921 };
3922
3923 //------------------------------------------------------------------------
3924
3925 class TextGeneratorFactory
3926 {
3927   public:
3928     static TextGeneratorFactory *instance()
3929     {
3930       static TextGeneratorFactory *instance = 0;
3931       if (instance==0) instance = new TextGeneratorFactory;
3932       return instance;
3933     }
3934     TextGeneratorIntf *create(FTextStream &ts,const QCString &relPath)
3935     {
3936       switch (g_globals.outputFormat)
3937       {
3938         case ContextOutputFormat_Html:
3939           return new TextGeneratorHtml(ts,relPath);
3940         case ContextOutputFormat_Latex:
3941           return new TextGeneratorLatex(ts);
3942         default:
3943           break;
3944       }
3945       return 0;
3946     }
3947   private:
3948     TextGeneratorFactory() {}
3949     virtual ~TextGeneratorFactory() {}
3950 };
3951
3952 TemplateVariant createLinkedText(Definition *def,const QCString &relPath,const QCString &text)
3953 {
3954   QGString s;
3955   FTextStream ts(&s);
3956   TextGeneratorIntf *tg = TextGeneratorFactory::instance()->create(ts,relPath);
3957   if (tg)
3958   {
3959     linkifyText(*tg,def->getOuterScope(),def->getBodyDef(),def,text);
3960     delete tg;
3961     return TemplateVariant(s.data(),TRUE);
3962   }
3963   else
3964   {
3965     return text;
3966   }
3967 }
3968
3969 //%% struct Member(Symbol): member information
3970 //%% {
3971 class MemberContext::Private : public DefinitionContext<MemberContext::Private>
3972 {
3973   public:
3974     Private(MemberDef *md) : DefinitionContext<MemberContext::Private>(md) , m_memberDef(md)
3975     {
3976       static bool init=FALSE;
3977       if (!init)
3978       {
3979         addBaseProperties(s_inst);
3980         s_inst.addProperty("isSignal",            &Private::isSignal);
3981         s_inst.addProperty("isSlot",              &Private::isSlot);
3982         s_inst.addProperty("isVariable",          &Private::isVariable);
3983         s_inst.addProperty("isEnumeration",       &Private::isEnumeration);
3984         s_inst.addProperty("isEnumValue",         &Private::isEnumValue);
3985         s_inst.addProperty("isTypedef",           &Private::isTypedef);
3986         s_inst.addProperty("isFunction",          &Private::isFunction);
3987         s_inst.addProperty("isFunctionPtr",       &Private::isFunctionPtr);
3988         s_inst.addProperty("isDefine",            &Private::isDefine);
3989         s_inst.addProperty("isFriend",            &Private::isFriend);
3990         s_inst.addProperty("isProperty",          &Private::isProperty);
3991         s_inst.addProperty("isEvent",             &Private::isEvent);
3992         s_inst.addProperty("isRelated",           &Private::isRelated);
3993         s_inst.addProperty("isForeign",           &Private::isForeign);
3994         s_inst.addProperty("isStatic",            &Private::isStatic);
3995         s_inst.addProperty("isInline",            &Private::isInline);
3996         s_inst.addProperty("isExplicit",          &Private::isExplicit);
3997         s_inst.addProperty("isMutable",           &Private::isMutable);
3998         s_inst.addProperty("isGettable",          &Private::isGettable);
3999         s_inst.addProperty("isPrivateGettable",   &Private::isPrivateGettable);
4000         s_inst.addProperty("isProtectedGettable", &Private::isProtectedGettable);
4001         s_inst.addProperty("isSettable",          &Private::isSettable);
4002         s_inst.addProperty("isPrivateSettable",   &Private::isPrivateSettable);
4003         s_inst.addProperty("isProtectedSettable", &Private::isProtectedSettable);
4004         s_inst.addProperty("isReadable",          &Private::isReadable);
4005         s_inst.addProperty("isWritable",          &Private::isWritable);
4006         s_inst.addProperty("isAddable",           &Private::isAddable);
4007         s_inst.addProperty("isRemovable",         &Private::isRemovable);
4008         s_inst.addProperty("isRaisable",          &Private::isRaisable);
4009         s_inst.addProperty("isFinal",             &Private::isFinal);
4010         s_inst.addProperty("isAbstract",          &Private::isAbstract);
4011         s_inst.addProperty("isOverride",          &Private::isOverride);
4012         s_inst.addProperty("isInitonly",          &Private::isInitonly);
4013         s_inst.addProperty("isOptional",          &Private::isOptional);
4014         s_inst.addProperty("isRequired",          &Private::isRequired);
4015         s_inst.addProperty("isNonAtomic",         &Private::isNonAtomic);
4016         s_inst.addProperty("isCopy",              &Private::isCopy);
4017         s_inst.addProperty("isAssign",            &Private::isAssign);
4018         s_inst.addProperty("isRetain",            &Private::isRetain);
4019         s_inst.addProperty("isWeak",              &Private::isWeak);
4020         s_inst.addProperty("isStrong",            &Private::isStrong);
4021         s_inst.addProperty("isUnretained",        &Private::isUnretained);
4022         s_inst.addProperty("isNew",               &Private::isNew);
4023         s_inst.addProperty("isSealed",            &Private::isSealed);
4024         s_inst.addProperty("isImplementation",    &Private::isImplementation);
4025         s_inst.addProperty("isExternal",          &Private::isExternal);
4026         s_inst.addProperty("isAlias",             &Private::isAlias);
4027         s_inst.addProperty("isDefault",           &Private::isDefault);
4028         s_inst.addProperty("isDelete",            &Private::isDelete);
4029         s_inst.addProperty("isNoExcept",          &Private::isNoExcept);
4030         s_inst.addProperty("isAttribute",         &Private::isAttribute);
4031         s_inst.addProperty("isUNOProperty",       &Private::isUNOProperty);
4032         s_inst.addProperty("isReadonly",          &Private::isReadonly);
4033         s_inst.addProperty("isBound",             &Private::isBound);
4034         s_inst.addProperty("isConstrained",       &Private::isConstrained);
4035         s_inst.addProperty("isTransient",         &Private::isTransient);
4036         s_inst.addProperty("isMaybeVoid",         &Private::isMaybeVoid);
4037         s_inst.addProperty("isMaybeDefault",      &Private::isMaybeDefault);
4038         s_inst.addProperty("isMaybeAmbiguous",    &Private::isMaybeAmbiguous);
4039         s_inst.addProperty("isPublished",         &Private::isPublished);
4040         s_inst.addProperty("isTemplateSpecialization",&Private::isTemplateSpecialization);
4041         s_inst.addProperty("isObjCMethod",        &Private::isObjCMethod);
4042         s_inst.addProperty("isObjCProperty",      &Private::isObjCProperty);
4043         s_inst.addProperty("isAnonymous",         &Private::isAnonymous);
4044         s_inst.addProperty("hasParameters",       &Private::hasParameters);
4045         s_inst.addProperty("declType",            &Private::declType);
4046         s_inst.addProperty("declArgs",            &Private::declArgs);
4047         s_inst.addProperty("anonymousType",       &Private::anonymousType);
4048         s_inst.addProperty("anonymousMember",     &Private::anonymousMember);
4049         s_inst.addProperty("hasDetails",          &Private::hasDetails);
4050         s_inst.addProperty("exception",           &Private::exception);
4051         s_inst.addProperty("bitfields",           &Private::bitfields);
4052         s_inst.addProperty("initializer",         &Private::initializer);
4053         s_inst.addProperty("initializerAsCode",   &Private::initializerAsCode);
4054         s_inst.addProperty("hasOneLineInitializer",   &Private::hasOneLineInitializer);
4055         s_inst.addProperty("hasMultiLineInitializer", &Private::hasMultiLineInitializer);
4056         s_inst.addProperty("templateArgs",        &Private::templateArgs);
4057         s_inst.addProperty("templateAlias",       &Private::templateAlias);
4058         s_inst.addProperty("propertyAttrs",       &Private::propertyAttrs);
4059         s_inst.addProperty("eventAttrs",          &Private::eventAttrs);
4060         s_inst.addProperty("category",            &Private::category);
4061         s_inst.addProperty("categoryRelation",    &Private::categoryRelation);
4062         s_inst.addProperty("class",               &Private::getClass);
4063         s_inst.addProperty("file",                &Private::getFile);
4064         s_inst.addProperty("namespace",           &Private::getNamespace);
4065         s_inst.addProperty("definition",          &Private::definition);
4066         s_inst.addProperty("parameters",          &Private::parameters);
4067         s_inst.addProperty("hasConstQualifier",   &Private::hasConstQualifier);
4068         s_inst.addProperty("hasVolatileQualifier",&Private::hasVolatileQualifier);
4069         s_inst.addProperty("hasRefQualifierLValue", &Private::hasRefQualifierLValue);
4070         s_inst.addProperty("hasRefQualifierRValue", &Private::hasRefQualifierRValue);
4071         s_inst.addProperty("trailingReturnType",  &Private::trailingReturnType);
4072         s_inst.addProperty("extraTypeChars",      &Private::extraTypeChars);
4073         s_inst.addProperty("templateDecls",       &Private::templateDecls);
4074         s_inst.addProperty("labels",              &Private::labels);
4075         s_inst.addProperty("enumBaseType",        &Private::enumBaseType);
4076         s_inst.addProperty("enumValues",          &Private::enumValues);
4077         s_inst.addProperty("paramDocs",           &Private::paramDocs);
4078         s_inst.addProperty("reimplements",        &Private::reimplements);
4079         s_inst.addProperty("implements",          &Private::implements);
4080         s_inst.addProperty("reimplementedBy",     &Private::reimplementedBy);
4081         s_inst.addProperty("implementedBy",       &Private::implementedBy);
4082         s_inst.addProperty("examples",            &Private::examples);
4083         s_inst.addProperty("typeConstraints",     &Private::typeConstraints);
4084         s_inst.addProperty("functionQualifier",   &Private::functionQualifier);
4085         s_inst.addProperty("sourceRefs",          &Private::sourceRefs);
4086         s_inst.addProperty("sourceRefBys",        &Private::sourceRefBys);
4087         s_inst.addProperty("hasSources",          &Private::hasSources);
4088         s_inst.addProperty("sourceCode",          &Private::sourceCode);
4089         s_inst.addProperty("hasCallGraph",        &Private::hasCallGraph);
4090         s_inst.addProperty("callGraph",           &Private::callGraph);
4091         s_inst.addProperty("hasCallerGraph",      &Private::hasCallerGraph);
4092         s_inst.addProperty("callerGraph",         &Private::callerGraph);
4093         s_inst.addProperty("hasReferencedByRelation", &Private::hasReferencedByRelation);
4094         s_inst.addProperty("referencedByRelation",    &Private::referencedByRelation);
4095         s_inst.addProperty("hasReferencesRelation",   &Private::hasReferencesRelation);
4096         s_inst.addProperty("referencesRelation",      &Private::referencesRelation);
4097         s_inst.addProperty("fieldType",           &Private::fieldType);
4098         s_inst.addProperty("type",                &Private::type);
4099         s_inst.addProperty("detailsVisibleFor",   &Private::detailsVisibleFor);
4100         s_inst.addProperty("nameWithContextFor",  &Private::nameWithContextFor);
4101         init=TRUE;
4102       }
4103       if (!md->cookie()) { md->setCookie(new MemberContext::Private::Cachable(md)); }
4104
4105       Cachable &cache = getCache();
4106       cache.propertyAttrs.reset(TemplateList::alloc());
4107       if (md && md->isProperty())
4108       {
4109         if (md->isGettable())           cache.propertyAttrs->append("get");
4110         if (md->isPrivateGettable())    cache.propertyAttrs->append("private get");
4111         if (md->isProtectedGettable())  cache.propertyAttrs->append("protected get");
4112         if (md->isSettable())           cache.propertyAttrs->append("set");
4113         if (md->isPrivateSettable())    cache.propertyAttrs->append("private set");
4114         if (md->isProtectedSettable())  cache.propertyAttrs->append("protected set");
4115       }
4116       cache.eventAttrs.reset(TemplateList::alloc());
4117       if (md && md->isEvent())
4118       {
4119         if (md->isAddable())   cache.eventAttrs->append("add");
4120         if (md->isRemovable()) cache.eventAttrs->append("remove");
4121         if (md->isRaisable())  cache.eventAttrs->append("raise");
4122       }
4123     }
4124     virtual ~Private() {}
4125     TemplateVariant get(const char *n) const
4126     {
4127       return s_inst.get(this,n);
4128     }
4129     TemplateVariant fieldType() const
4130     {
4131       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->fieldType());
4132     }
4133     TemplateVariant declType() const
4134     {
4135       Cachable &cache = getCache();
4136       if (!cache.declTypeParsed)
4137       {
4138         cache.declType=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->getDeclType());
4139         cache.declTypeParsed = TRUE;
4140         return cache.declType;
4141       }
4142       else
4143       {
4144         return cache.declType;
4145       }
4146     }
4147     TemplateVariant declArgs() const
4148     {
4149       Cachable &cache = getCache();
4150       if (!cache.declArgsParsed)
4151       {
4152         cache.declArgs=createLinkedText(m_memberDef,relPathAsString(),m_memberDef->argsString());
4153         cache.declArgsParsed = TRUE;
4154         return cache.declArgs;
4155       }
4156       else
4157       {
4158         return cache.declArgs;
4159       }
4160     }
4161     TemplateVariant exception() const
4162     {
4163       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->excpString());
4164     }
4165     TemplateVariant bitfields() const
4166     {
4167       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->bitfieldString());
4168     }
4169     TemplateVariant isStatic() const
4170     {
4171       return m_memberDef->isStatic();
4172     }
4173     TemplateVariant isObjCMethod() const
4174     {
4175       return m_memberDef->isObjCMethod();
4176     }
4177     TemplateVariant isObjCProperty() const
4178     {
4179       return m_memberDef->isObjCProperty();
4180     }
4181     TemplateVariant isImplementation() const
4182     {
4183       return m_memberDef->isImplementation();
4184     }
4185     TemplateVariant isSignal() const
4186     {
4187       return m_memberDef->isSignal();
4188     }
4189     TemplateVariant isSlot() const
4190     {
4191       return m_memberDef->isSlot();
4192     }
4193     TemplateVariant isTypedef() const
4194     {
4195       return m_memberDef->isTypedef();
4196     }
4197     TemplateVariant isFunction() const
4198     {
4199       return m_memberDef->isFunction();
4200     }
4201     TemplateVariant isFunctionPtr() const
4202     {
4203       return m_memberDef->isFunctionPtr();
4204     }
4205     TemplateVariant isFriend() const
4206     {
4207       return m_memberDef->isFriend();
4208     }
4209     TemplateVariant isForeign() const
4210     {
4211       return m_memberDef->isForeign();
4212     }
4213     TemplateVariant isEvent() const
4214     {
4215       return m_memberDef->isEvent();
4216     }
4217     TemplateVariant isInline() const
4218     {
4219       return m_memberDef->isInline();
4220     }
4221     TemplateVariant isExplicit() const
4222     {
4223       return m_memberDef->isExplicit();
4224     }
4225     TemplateVariant isMutable() const
4226     {
4227       return m_memberDef->isMutable();
4228     }
4229     TemplateVariant isGettable() const
4230     {
4231       return m_memberDef->isGettable();
4232     }
4233     TemplateVariant isPrivateGettable() const
4234     {
4235       return m_memberDef->isPrivateGettable();
4236     }
4237     TemplateVariant isProtectedGettable() const
4238     {
4239       return m_memberDef->isProtectedGettable();
4240     }
4241     TemplateVariant isSettable() const
4242     {
4243       return m_memberDef->isSettable();
4244     }
4245     TemplateVariant isPrivateSettable() const
4246     {
4247       return m_memberDef->isPrivateSettable();
4248     }
4249     TemplateVariant isProtectedSettable() const
4250     {
4251       return m_memberDef->isProtectedSettable();
4252     }
4253     TemplateVariant isReadable() const
4254     {
4255       return m_memberDef->isReadable();
4256     }
4257     TemplateVariant isWritable() const
4258     {
4259       return m_memberDef->isWritable();
4260     }
4261     TemplateVariant isAddable() const
4262     {
4263       return m_memberDef->isAddable();
4264     }
4265     TemplateVariant isRemovable() const
4266     {
4267       return m_memberDef->isRemovable();
4268     }
4269     TemplateVariant isRaisable() const
4270     {
4271       return m_memberDef->isRaisable();
4272     }
4273     TemplateVariant isFinal() const
4274     {
4275       return m_memberDef->isFinal();
4276     }
4277     TemplateVariant isAbstract() const
4278     {
4279       return m_memberDef->isAbstract();
4280     }
4281     TemplateVariant isOverride() const
4282     {
4283       return m_memberDef->isOverride();
4284     }
4285     TemplateVariant isInitonly() const
4286     {
4287       return m_memberDef->isInitonly();
4288     }
4289     TemplateVariant isOptional() const
4290     {
4291       return m_memberDef->isOptional();
4292     }
4293     TemplateVariant isRequired() const
4294     {
4295       return m_memberDef->isRequired();
4296     }
4297     TemplateVariant isNonAtomic() const
4298     {
4299       return m_memberDef->isNonAtomic();
4300     }
4301     TemplateVariant isCopy() const
4302     {
4303       return m_memberDef->isCopy();
4304     }
4305     TemplateVariant isAssign() const
4306     {
4307       return m_memberDef->isAssign();
4308     }
4309     TemplateVariant isRetain() const
4310     {
4311       return m_memberDef->isRetain();
4312     }
4313     TemplateVariant isWeak() const
4314     {
4315       return m_memberDef->isWeak();
4316     }
4317     TemplateVariant isStrong() const
4318     {
4319       return m_memberDef->isStrong();
4320     }
4321     TemplateVariant isUnretained() const
4322     {
4323       return m_memberDef->isUnretained();
4324     }
4325     TemplateVariant isNew() const
4326     {
4327       return m_memberDef->isNew();
4328     }
4329     TemplateVariant isSealed() const
4330     {
4331       return m_memberDef->isSealed();
4332     }
4333     TemplateVariant isExternal() const
4334     {
4335       return m_memberDef->isExternal();
4336     }
4337     TemplateVariant isAlias() const
4338     {
4339       return m_memberDef->isAlias();
4340     }
4341     TemplateVariant isDefault() const
4342     {
4343       return m_memberDef->isDefault();
4344     }
4345     TemplateVariant isDelete() const
4346     {
4347       return m_memberDef->isDelete();
4348     }
4349     TemplateVariant isNoExcept() const
4350     {
4351       return m_memberDef->isNoExcept();
4352     }
4353     TemplateVariant isAttribute() const
4354     {
4355       return m_memberDef->isAttribute();
4356     }
4357     TemplateVariant isUNOProperty() const
4358     {
4359       return m_memberDef->isUNOProperty();
4360     }
4361     TemplateVariant isReadonly() const
4362     {
4363       return m_memberDef->isReadonly();
4364     }
4365     TemplateVariant isBound() const
4366     {
4367       return m_memberDef->isBound();
4368     }
4369     TemplateVariant isConstrained() const
4370     {
4371       return m_memberDef->isConstrained();
4372     }
4373     TemplateVariant isTransient() const
4374     {
4375       return m_memberDef->isTransient();
4376     }
4377     TemplateVariant isMaybeVoid() const
4378     {
4379       return m_memberDef->isMaybeVoid();
4380     }
4381     TemplateVariant isMaybeDefault() const
4382     {
4383       return m_memberDef->isMaybeDefault();
4384     }
4385     TemplateVariant isMaybeAmbiguous() const
4386     {
4387       return m_memberDef->isMaybeAmbiguous();
4388     }
4389     TemplateVariant isPublished() const
4390     {
4391       return m_memberDef->isPublished();
4392     }
4393     TemplateVariant isTemplateSpecialization() const
4394     {
4395       return m_memberDef->isTemplateSpecialization();
4396     }
4397     TemplateVariant isProperty() const
4398     {
4399       return m_memberDef->isProperty();
4400     }
4401     TemplateVariant isEnumValue() const
4402     {
4403       return m_memberDef->isEnumValue();
4404     }
4405     TemplateVariant isVariable() const
4406     {
4407       return m_memberDef->isVariable();
4408     }
4409     TemplateVariant isEnumeration() const
4410     {
4411       return m_memberDef->isEnumerate();
4412     }
4413     TemplateVariant hasDetails() const
4414     {
4415       return m_memberDef->isDetailedSectionLinkable();
4416     }
4417     TemplateVariant initializer() const
4418     {
4419       return createLinkedText(m_memberDef,relPathAsString(),m_memberDef->initializer());
4420     }
4421     TemplateVariant initializerAsCode() const
4422     {
4423       Cachable &cache = getCache();
4424       if (!cache.initializerParsed)
4425       {
4426         QCString scopeName;
4427         if (m_memberDef->getClassDef())
4428         {
4429           scopeName = m_memberDef->getClassDef()->name();
4430         }
4431         else if (m_memberDef->getNamespaceDef())
4432         {
4433           scopeName = m_memberDef->getNamespaceDef()->name();
4434         }
4435         cache.initializer = parseCode(m_memberDef,scopeName,relPathAsString(),
4436                                         m_memberDef->initializer());
4437         cache.initializerParsed = TRUE;
4438       }
4439       return cache.initializer;
4440     }
4441     TemplateVariant isDefine() const
4442     {
4443       return m_memberDef->isDefine();
4444     }
4445     TemplateVariant isAnonymous() const
4446     {
4447       QCString name = m_memberDef->name();
4448       return !name.isEmpty() && name.at(0)=='@';
4449     }
4450     TemplateVariant anonymousType() const
4451     {
4452       Cachable &cache = getCache();
4453       if (!cache.anonymousType)
4454       {
4455         ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
4456         if (cd)
4457         {
4458           cache.anonymousType.reset(ClassContext::alloc(cd));
4459         }
4460       }
4461       if (cache.anonymousType)
4462       {
4463         return cache.anonymousType.get();
4464       }
4465       else
4466       {
4467         return FALSE;
4468       }
4469     }
4470     TemplateVariant anonymousMember() const
4471     {
4472       Cachable &cache = getCache();
4473       if (!cache.anonymousMember)
4474       {
4475         MemberDef *md = m_memberDef->fromAnonymousMember();
4476         if (md)
4477         {
4478           cache.anonymousMember.reset(MemberContext::alloc(md));
4479         }
4480       }
4481       if (cache.anonymousMember)
4482       {
4483         return cache.anonymousMember.get();
4484       }
4485       else
4486       {
4487         return FALSE;
4488       }
4489     }
4490     TemplateVariant isRelated() const
4491     {
4492       return m_memberDef->isRelated();
4493     }
4494     TemplateVariant enumBaseType() const
4495     {
4496       return m_memberDef->enumBaseType();
4497     }
4498     TemplateVariant hasOneLineInitializer() const
4499     {
4500       return m_memberDef->hasOneLineInitializer();
4501     }
4502     TemplateVariant hasMultiLineInitializer() const
4503     {
4504       return m_memberDef->hasMultiLineInitializer();
4505     }
4506     TemplateVariant enumValues() const
4507     {
4508       Cachable &cache = getCache();
4509       if (!cache.enumValues)
4510       {
4511         MemberList *ml = m_memberDef->enumFieldList();
4512         if (ml)
4513         {
4514           cache.enumValues.reset(MemberListContext::alloc(ml));
4515         }
4516         else
4517         {
4518           cache.enumValues.reset(MemberListContext::alloc());
4519         }
4520       }
4521       return cache.enumValues.get();
4522     }
4523     TemplateVariant templateArgs() const
4524     {
4525       Cachable &cache = getCache();
4526       if (!cache.templateArgs && m_memberDef->templateArguments())
4527       {
4528         cache.templateArgs.reset(ArgumentListContext::alloc(m_memberDef->templateArguments(),m_memberDef,relPathAsString()));
4529       }
4530       if (cache.templateArgs)
4531       {
4532         return cache.templateArgs.get();
4533       }
4534       else
4535       {
4536         return TemplateVariant(FALSE);
4537       }
4538     }
4539     TemplateVariant templateAlias() const
4540     {
4541       if (m_memberDef->isAlias())
4542       {
4543         return createLinkedText(m_memberDef,relPathAsString(),
4544                                 QCString(" = ")+m_memberDef->typeString());
4545       }
4546       return "";
4547     }
4548     TemplateVariant propertyAttrs() const
4549     {
4550       return getCache().propertyAttrs.get();
4551     }
4552     TemplateVariant eventAttrs() const
4553     {
4554       return getCache().eventAttrs.get();
4555     }
4556     TemplateVariant getClass() const
4557     {
4558       Cachable &cache = getCache();
4559       if (!cache.classDef && m_memberDef->getClassDef())
4560       {
4561         cache.classDef.reset(ClassContext::alloc(m_memberDef->getClassDef()));
4562       }
4563       if (cache.classDef)
4564       {
4565         return cache.classDef.get();
4566       }
4567       else
4568       {
4569         return TemplateVariant(FALSE);
4570       }
4571     }
4572     TemplateVariant category() const
4573     {
4574       Cachable &cache = getCache();
4575       if (!cache.category && m_memberDef->category())
4576       {
4577         cache.category.reset(ClassContext::alloc(m_memberDef->category()));
4578       }
4579       if (cache.category)
4580       {
4581         return cache.category.get();
4582       }
4583       else
4584       {
4585         return TemplateVariant(FALSE);
4586       }
4587     }
4588     TemplateVariant categoryRelation() const
4589     {
4590       Cachable &cache = getCache();
4591       if (!cache.categoryRelation && m_memberDef->categoryRelation())
4592       {
4593         cache.categoryRelation.reset(MemberContext::alloc(m_memberDef->categoryRelation()));
4594       }
4595       if (cache.categoryRelation)
4596       {
4597         return cache.categoryRelation.get();
4598       }
4599       else
4600       {
4601         return TemplateVariant(FALSE);
4602       }
4603     }
4604     TemplateVariant getFile() const
4605     {
4606       Cachable &cache = getCache();
4607       if (!cache.fileDef && m_memberDef->getFileDef())
4608       {
4609         cache.fileDef.reset(FileContext::alloc(m_memberDef->getFileDef()));
4610       }
4611       if (cache.fileDef)
4612       {
4613         return cache.fileDef.get();
4614       }
4615       else
4616       {
4617         return TemplateVariant(FALSE);
4618       }
4619     }
4620     TemplateVariant getNamespace() const
4621     {
4622       Cachable &cache = getCache();
4623       if (!cache.namespaceDef && m_memberDef->getNamespaceDef())
4624       {
4625         cache.namespaceDef.reset(NamespaceContext::alloc(m_memberDef->getNamespaceDef()));
4626       }
4627       if (cache.namespaceDef)
4628       {
4629         return cache.namespaceDef.get();
4630       }
4631       else
4632       {
4633         return TemplateVariant(FALSE);
4634       }
4635     }
4636     TemplateVariant definition() const
4637     {
4638       return createLinkedText(m_memberDef,relPathAsString(),
4639                               m_memberDef->displayDefinition());
4640     }
4641     ArgumentList *getDefArgList() const
4642     {
4643       return (m_memberDef->isDocsForDefinition()) ?
4644               m_memberDef->argumentList() : m_memberDef->declArgumentList();
4645     }
4646     TemplateVariant parameters() const
4647     {
4648       Cachable &cache = getCache();
4649       if (!cache.arguments)
4650       {
4651         ArgumentList *defArgList = getDefArgList();
4652         if (defArgList && !m_memberDef->isProperty())
4653         {
4654           cache.arguments.reset(ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()));
4655         }
4656         else
4657         {
4658           cache.arguments.reset(ArgumentListContext::alloc());
4659         }
4660       }
4661       return cache.arguments.get();
4662     }
4663     TemplateVariant hasParameters() const
4664     {
4665       return getDefArgList()!=0;
4666     }
4667     TemplateVariant hasConstQualifier() const
4668     {
4669       ArgumentList *al = getDefArgList();
4670       return al ? al->constSpecifier : FALSE;
4671     }
4672     TemplateVariant hasVolatileQualifier() const
4673     {
4674       ArgumentList *al = getDefArgList();
4675       return al ? al->volatileSpecifier : FALSE;
4676     }
4677     TemplateVariant hasRefQualifierLValue() const
4678     {
4679       ArgumentList *al = getDefArgList();
4680       return al ? al->refQualifier==RefQualifierLValue : FALSE;
4681     }
4682     TemplateVariant hasRefQualifierRValue() const
4683     {
4684       ArgumentList *al = getDefArgList();
4685       return al ? al->refQualifier==RefQualifierRValue : FALSE;
4686     }
4687     TemplateVariant trailingReturnType() const
4688     {
4689       ArgumentList *al = getDefArgList();
4690       if (al && !al->trailingReturnType.isEmpty())
4691       {
4692         return createLinkedText(m_memberDef,relPathAsString(),
4693                                 al->trailingReturnType);
4694       }
4695       else
4696       {
4697         return "";
4698       }
4699     }
4700     TemplateVariant extraTypeChars() const
4701     {
4702       return m_memberDef->extraTypeChars();
4703     }
4704     void addTemplateDecls(TemplateList *tl) const
4705     {
4706       ClassDef *cd=m_memberDef->getClassDef();
4707       if (m_memberDef->definitionTemplateParameterLists())
4708       {
4709         QListIterator<ArgumentList> ali(*m_memberDef->definitionTemplateParameterLists());
4710         ArgumentList *tal;
4711         for (ali.toFirst();(tal=ali.current());++ali)
4712         {
4713           if (tal->count()>0)
4714           {
4715             ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString());
4716             tl->append(al);
4717           }
4718         }
4719       }
4720       else
4721       {
4722         if (cd && !m_memberDef->isRelated() && !m_memberDef->isTemplateSpecialization())
4723         {
4724           QList<ArgumentList> tempParamLists;
4725           cd->getTemplateParameterLists(tempParamLists);
4726           //printf("#tempParamLists=%d\n",tempParamLists.count());
4727           QListIterator<ArgumentList> ali(tempParamLists);
4728           ArgumentList *tal;
4729           for (ali.toFirst();(tal=ali.current());++ali)
4730           {
4731             if (tal->count()>0)
4732             {
4733               ArgumentListContext *al = ArgumentListContext::alloc(tal,m_memberDef,relPathAsString());
4734               tl->append(al);
4735             }
4736           }
4737         }
4738         if (m_memberDef->templateArguments()) // function template prefix
4739         {
4740           ArgumentListContext *al = ArgumentListContext::alloc(
4741               m_memberDef->templateArguments(),m_memberDef,relPathAsString());
4742           tl->append(al);
4743         }
4744       }
4745     }
4746     TemplateVariant templateDecls() const
4747     {
4748       Cachable &cache = getCache();
4749       if (!cache.templateDecls)
4750       {
4751         TemplateList *tl = TemplateList::alloc();
4752         addTemplateDecls(tl);
4753         cache.templateDecls.reset(tl);
4754       }
4755       return cache.templateDecls.get();
4756     }
4757     TemplateVariant labels() const
4758     {
4759       Cachable &cache = getCache();
4760       if (!cache.labels)
4761       {
4762         QStrList sl;
4763         m_memberDef->getLabels(sl,m_memberDef->getOuterScope());
4764         TemplateList *tl = TemplateList::alloc();
4765         if (sl.count()>0)
4766         {
4767           QStrListIterator it(sl);
4768           for (;it.current();++it)
4769           {
4770             tl->append(*it);
4771           }
4772         }
4773         cache.labels.reset(tl);
4774       }
4775       return cache.labels.get();
4776     }
4777     TemplateVariant paramDocs() const
4778     {
4779       Cachable &cache = getCache();
4780       if (!cache.paramDocs)
4781       {
4782         if (m_memberDef->argumentList() && m_memberDef->argumentList()->hasDocumentation())
4783         {
4784           QCString paramDocs;
4785           ArgumentListIterator ali(*m_memberDef->argumentList());
4786           Argument *a;
4787           // convert the parameter documentation into a list of @param commands
4788           for (ali.toFirst();(a=ali.current());++ali)
4789           {
4790             if (a->hasDocumentation())
4791             {
4792               QCString direction = extractDirection(a->docs);
4793               paramDocs+="@param"+direction+" "+a->name+" "+a->docs;
4794             }
4795           }
4796           cache.paramDocs.reset(new TemplateVariant(parseDoc(m_memberDef,
4797                                            m_memberDef->docFile(),m_memberDef->docLine(),
4798                                            relPathAsString(),paramDocs,FALSE)));
4799         }
4800         else
4801         {
4802           cache.paramDocs.reset(new TemplateVariant(""));
4803         }
4804       }
4805       return *cache.paramDocs;
4806     }
4807     TemplateVariant implements() const
4808     {
4809       Cachable &cache = getCache();
4810       if (!cache.implements)
4811       {
4812         MemberDef *md = m_memberDef->reimplements();
4813         cache.implements.reset(TemplateList::alloc());
4814         if (md)
4815         {
4816           ClassDef *cd = md->getClassDef();
4817           if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
4818           {
4819             MemberContext *mc = MemberContext::alloc(md);
4820             cache.implements->append(mc);
4821           }
4822         }
4823       }
4824       return cache.implements.get();
4825     }
4826     TemplateVariant reimplements() const
4827     {
4828       Cachable &cache = getCache();
4829       if (!cache.reimplements)
4830       {
4831         MemberDef *md = m_memberDef->reimplements();
4832         cache.reimplements.reset(TemplateList::alloc());
4833         if (md)
4834         {
4835           ClassDef *cd = md->getClassDef();
4836           if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
4837           {
4838             MemberContext *mc = MemberContext::alloc(md);
4839             cache.reimplements->append(mc);
4840           }
4841         }
4842       }
4843       return cache.reimplements.get();
4844     }
4845     TemplateVariant implementedBy() const
4846     {
4847       Cachable &cache = getCache();
4848       if (!cache.implementedBy)
4849       {
4850         MemberList *ml = m_memberDef->reimplementedBy();
4851         cache.implementedBy.reset(TemplateList::alloc());
4852         if (ml)
4853         {
4854           MemberListIterator mli(*ml);
4855           MemberDef *md=0;
4856           for (mli.toFirst();(md=mli.current());++mli)
4857           {
4858             ClassDef *cd = md->getClassDef();
4859             if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
4860             {
4861               MemberContext *mc = new MemberContext(md);
4862               cache.implementedBy->append(mc);
4863             }
4864           }
4865         }
4866       }
4867       return cache.implementedBy.get();
4868     }
4869     TemplateVariant reimplementedBy() const
4870     {
4871       Cachable &cache = getCache();
4872       if (!cache.reimplementedBy)
4873       {
4874         cache.reimplementedBy.reset(TemplateList::alloc());
4875         MemberList *ml = m_memberDef->reimplementedBy();
4876         if (ml)
4877         {
4878           MemberListIterator mli(*ml);
4879           MemberDef *md=0;
4880           for (mli.toFirst();(md=mli.current());++mli)
4881           {
4882             ClassDef *cd = md->getClassDef();
4883             if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
4884             {
4885               MemberContext *mc = new MemberContext(md);
4886               cache.reimplementedBy->append(mc);
4887             }
4888           }
4889         }
4890       }
4891       return cache.reimplementedBy.get();
4892     }
4893     void addExamples(TemplateList *list) const
4894     {
4895       if (m_memberDef->hasExamples())
4896       {
4897         ExampleSDict::Iterator it(*m_memberDef->getExamples());
4898         Example *ex;
4899         for (it.toFirst();(ex=it.current());++it)
4900         {
4901           TemplateStruct *s = TemplateStruct::alloc();
4902           s->set("text",ex->name);
4903           s->set("isLinkable",TRUE);
4904           s->set("anchor",ex->anchor);
4905           s->set("fileName",ex->file);
4906           s->set("isReference",FALSE);
4907           s->set("externalReference","");
4908           list->append(s);
4909         }
4910       }
4911     }
4912     TemplateVariant examples() const
4913     {
4914       Cachable &cache = getCache();
4915       if (!cache.examples)
4916       {
4917         TemplateList *exampleList = TemplateList::alloc();
4918         addExamples(exampleList);
4919         cache.examples.reset(exampleList);
4920       }
4921       return cache.examples.get();
4922     }
4923     TemplateVariant typeConstraints() const
4924     {
4925       Cachable &cache = getCache();
4926       if (!cache.typeConstraints && m_memberDef->typeConstraints())
4927       {
4928         cache.typeConstraints.reset(ArgumentListContext::alloc(m_memberDef->typeConstraints(),m_memberDef,relPathAsString()));
4929       }
4930       else
4931       {
4932         cache.typeConstraints.reset(ArgumentListContext::alloc());
4933       }
4934       return cache.typeConstraints.get();
4935     }
4936     TemplateVariant functionQualifier() const
4937     {
4938       if (!m_memberDef->isObjCMethod() &&
4939           (m_memberDef->isFunction()  || m_memberDef->isSlot() ||
4940            m_memberDef->isPrototype() || m_memberDef->isSignal()
4941           )
4942          )
4943       {
4944         return "()";
4945       }
4946       else
4947       {
4948         return "";
4949       }
4950     }
4951     TemplateVariant sourceRefs() const
4952     {
4953       Cachable &cache = getCache();
4954       if (!cache.sourceRefs)
4955       {
4956         cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers(),TRUE));
4957       }
4958       return cache.sourceRefs.get();
4959     }
4960     TemplateVariant sourceRefBys() const
4961     {
4962       Cachable &cache = getCache();
4963       if (!cache.sourceRefBys)
4964       {
4965         cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers(),TRUE));
4966       }
4967       return cache.sourceRefBys.get();
4968     }
4969     TemplateVariant hasSources() const
4970     {
4971       return TemplateVariant(m_memberDef->hasSources());
4972     }
4973     TemplateVariant sourceCode() const
4974     {
4975       Cachable &cache = getCache();
4976       if (!cache.sourceCodeParsed)
4977       {
4978         QCString codeFragment;
4979         FileDef *fd   = m_memberDef->getBodyDef();
4980         int startLine = m_memberDef->getStartBodyLine();
4981         int endLine   = m_memberDef->getEndBodyLine();
4982         if (fd && readCodeFragment(fd->absFilePath(),
4983               startLine,endLine,codeFragment)
4984            )
4985         {
4986           QCString scopeName;
4987           if (m_memberDef->getClassDef())
4988           {
4989             scopeName = m_memberDef->getClassDef()->name();
4990           }
4991           else if (m_memberDef->getNamespaceDef())
4992           {
4993             scopeName = m_memberDef->getNamespaceDef()->name();
4994           }
4995           cache.sourceCode = parseCode(m_memberDef,scopeName,relPathAsString(),codeFragment,startLine,endLine,TRUE);
4996           cache.sourceCodeParsed = TRUE;
4997         }
4998       }
4999       return cache.sourceCode;
5000     }
5001     DotCallGraph *getCallGraph() const
5002     {
5003       Cachable &cache = getCache();
5004       if (!cache.callGraph)
5005       {
5006         cache.callGraph.reset(new DotCallGraph(m_memberDef,FALSE));
5007       }
5008       return cache.callGraph.get();
5009     }
5010     TemplateVariant hasCallGraph() const
5011     {
5012       static bool haveDot = Config_getBool(HAVE_DOT);
5013       if (m_memberDef->hasCallGraph() && haveDot &&
5014           (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
5015       {
5016         DotCallGraph *cg = getCallGraph();
5017         return !cg->isTooBig() && !cg->isTrivial();
5018       }
5019       return TemplateVariant(FALSE);
5020     }
5021     TemplateVariant hasReferencedByRelation() const
5022     {
5023       return TemplateVariant(m_memberDef->hasReferencedByRelation());
5024     }
5025     TemplateVariant callGraph() const
5026     {
5027       if (hasCallGraph().toBool())
5028       {
5029         DotCallGraph *cg = getCallGraph();
5030         QGString result;
5031         FTextStream t(&result);
5032         switch (g_globals.outputFormat)
5033         {
5034           case ContextOutputFormat_Html:
5035             {
5036               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
5037                   g_globals.outputDir,
5038                   g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
5039                   relPathAsString(),TRUE,g_globals.dynSectionId
5040                   );
5041             }
5042             break;
5043           case ContextOutputFormat_Latex:
5044             {
5045               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
5046                   g_globals.outputDir,
5047                   g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
5048                   relPathAsString(),TRUE,g_globals.dynSectionId
5049                   );
5050             }
5051             break;
5052             // TODO: support other generators
5053           default:
5054             err("context.cpp: output format not yet supported");
5055             break;
5056         }
5057         g_globals.dynSectionId++;
5058         return TemplateVariant(result.data(),TRUE);
5059       }
5060       else
5061       {
5062         return TemplateVariant("");
5063       }
5064     }
5065     TemplateVariant referencedByRelation() const
5066     {
5067       if (hasReferencedByRelation().toBool())
5068       {
5069         err("context.cpp: output format not yet supported");
5070       }
5071       return TemplateVariant("");
5072     }
5073     DotCallGraph *getCallerGraph() const
5074     {
5075       Cachable &cache = getCache();
5076       if (!cache.callerGraph)
5077       {
5078         cache.callerGraph.reset(new DotCallGraph(m_memberDef,TRUE));
5079       }
5080       return cache.callerGraph.get();
5081     }
5082     TemplateVariant hasCallerGraph() const
5083     {
5084       static bool haveDot = Config_getBool(HAVE_DOT);
5085       if (m_memberDef->hasCallerGraph() && haveDot &&
5086           (m_memberDef->isFunction() || m_memberDef->isSlot() || m_memberDef->isSignal()))
5087       {
5088         DotCallGraph *cg = getCallerGraph();
5089         return !cg->isTooBig() && !cg->isTrivial();
5090       }
5091       return TemplateVariant(FALSE);
5092     }
5093     TemplateVariant hasReferencesRelation() const
5094     {
5095       return TemplateVariant(m_memberDef->hasReferencesRelation());
5096     }
5097     TemplateVariant callerGraph() const
5098     {
5099       if (hasCallerGraph().toBool())
5100       {
5101         DotCallGraph *cg = getCallerGraph();
5102         QGString result;
5103         FTextStream t(&result);
5104         switch (g_globals.outputFormat)
5105         {
5106           case ContextOutputFormat_Html:
5107             {
5108               cg->writeGraph(t,GOF_BITMAP,EOF_Html,
5109                   g_globals.outputDir,
5110                   g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
5111                   relPathAsString(),TRUE,g_globals.dynSectionId
5112                   );
5113             }
5114             break;
5115           case ContextOutputFormat_Latex:
5116             {
5117               cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
5118                   g_globals.outputDir,
5119                   g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
5120                   relPathAsString(),TRUE,g_globals.dynSectionId
5121                   );
5122             }
5123             break;
5124             // TODO: support other generators
5125           default:
5126             err("context.cpp: output format not yet supported");
5127             break;
5128         }
5129         g_globals.dynSectionId++;
5130         return TemplateVariant(result.data(),TRUE);
5131       }
5132       else
5133       {
5134         return TemplateVariant("");
5135       }
5136     }
5137     TemplateVariant referencesRelation() const
5138     {
5139       if (hasReferencesRelation().toBool())
5140       {
5141          err("context.cpp: output format not yet supported");
5142       }
5143       return TemplateVariant("");
5144     }
5145     TemplateVariant type() const
5146     {
5147       return m_memberDef->typeString();
5148     }
5149     TemplateVariant handleDetailsVisibleFor(const QValueList<TemplateVariant> &args) const
5150     {
5151       if (args.count()==1)
5152       {
5153         return m_memberDef->isDetailedSectionVisible(args[0].toString()=="module",args[0].toString()=="file");
5154       }
5155       else
5156       {
5157         err(".detailsVisibleFor should take one string argument, got %d\n",args.count());
5158       }
5159       return TemplateVariant();
5160     }
5161     TemplateVariant detailsVisibleFor() const
5162     {
5163       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleDetailsVisibleFor>(this);
5164     }
5165     TemplateVariant handleNameWithContextFor(const QValueList<TemplateVariant> &args) const
5166     {
5167       if (args.count()==1)
5168       {
5169         SrcLangExt lang = m_memberDef->getLanguage();
5170         QCString n = m_memberDef->name();
5171         QCString ctx = args[0].toString();
5172         QCString sep = getLanguageSpecificSeparator(lang,TRUE);
5173         if (m_memberDef->getEnumScope() && m_memberDef->livesInsideEnum())
5174         {
5175           n.prepend(m_memberDef->getEnumScope()->displayName()+sep);
5176         }
5177         if (ctx=="module" && m_memberDef->getClassDef() && !m_memberDef->isRelated())
5178         {
5179           n.prepend(m_memberDef->getClassDef()->displayName()+sep);
5180         }
5181         else if ((ctx=="module" || ctx=="file") && m_memberDef->getNamespaceDef())
5182         {
5183           n.prepend(m_memberDef->getNamespaceDef()->displayName()+sep);
5184         }
5185         return n;
5186       }
5187       else
5188       {
5189         err(".nameWithContextFor should take one string argument, got %d\n",args.count());
5190       }
5191       return TemplateVariant();
5192     }
5193     TemplateVariant nameWithContextFor() const
5194     {
5195       return TemplateVariant::Delegate::fromMethod<Private,&Private::handleNameWithContextFor>(this);
5196     }
5197   private:
5198     MemberDef *m_memberDef;
5199     struct Cachable : public DefinitionContext<MemberContext::Private>::Cachable
5200     {
5201       Cachable(MemberDef *md) : DefinitionContext<MemberContext::Private>::Cachable(md),
5202                                 initializerParsed(FALSE), sourceCodeParsed(FALSE),
5203                                 declArgsParsed(FALSE), declTypeParsed(FALSE) { }
5204       SharedPtr<ArgumentListContext> templateArgs;
5205       SharedPtr<ArgumentListContext> arguments;
5206       SharedPtr<MemberListContext>   enumValues;
5207       SharedPtr<FileContext>         fileDef;
5208       SharedPtr<NamespaceContext>    namespaceDef;
5209       SharedPtr<ClassContext>        category;
5210       SharedPtr<MemberContext>       categoryRelation;
5211       SharedPtr<ClassContext>        classDef;
5212       SharedPtr<ClassContext>        anonymousType;
5213       SharedPtr<TemplateList>        templateDecls;
5214       ScopedPtr<TemplateVariant>     paramDocs;
5215       SharedPtr<TemplateList>        implements;
5216       SharedPtr<TemplateList>        reimplements;
5217       SharedPtr<TemplateList>        implementedBy;
5218       SharedPtr<MemberListContext>   sourceRefs;
5219       SharedPtr<MemberListContext>   sourceRefBys;
5220       ScopedPtr<DotCallGraph>        callGraph;
5221       ScopedPtr<DotCallGraph>        callerGraph;
5222       SharedPtr<MemberContext>       anonymousMember;
5223       SharedPtr<TemplateList>        reimplementedBy;
5224       SharedPtr<TemplateList>        labels;
5225       TemplateVariant                initializer;
5226       bool                           initializerParsed;
5227       TemplateVariant                sourceCode;
5228       bool                           sourceCodeParsed;
5229       TemplateVariant                declArgs;
5230       bool                           declArgsParsed;
5231       TemplateVariant                declType;
5232       bool                           declTypeParsed;
5233       SharedPtr<TemplateList>        examples;
5234       SharedPtr<TemplateList>        exampleList;
5235       SharedPtr<ArgumentListContext> typeConstraints;
5236       SharedPtr<TemplateList>        propertyAttrs;
5237       SharedPtr<TemplateList>        eventAttrs;
5238     };
5239     Cachable &getCache() const
5240     {
5241       Cachable *c = static_cast<Cachable*>(m_memberDef->cookie());
5242       assert(c!=0);
5243       return *c;
5244     }
5245     static PropertyMapper<MemberContext::Private> s_inst;
5246 };
5247 //%% }
5248
5249 PropertyMapper<MemberContext::Private> MemberContext::Private::s_inst;
5250
5251 MemberContext::MemberContext(MemberDef *md) : RefCountedContext("MemberContext")
5252 {
5253   p = new Private(md);
5254 }
5255
5256 MemberContext::~MemberContext()
5257 {
5258   delete p;
5259 }
5260
5261 TemplateVariant MemberContext::get(const char *n) const
5262 {
5263   return p->get(n);
5264 }
5265
5266
5267 //------------------------------------------------------------------------
5268
5269 //%% struct Module(Symbol): group information
5270 //%% {
5271 class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
5272 {
5273   public:
5274     Private(GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd)
5275     {
5276       static bool init=FALSE;
5277       if (!init)
5278       {
5279         addBaseProperties(s_inst);
5280         s_inst.addProperty("title",                     &Private::title);
5281         s_inst.addProperty("highlight",                 &Private::highlight);
5282         s_inst.addProperty("subhighlight",              &Private::subHighlight);
5283         s_inst.addProperty("hasGroupGraph",             &Private::hasGroupGraph);
5284         s_inst.addProperty("groupGraph",                &Private::groupGraph);
5285         s_inst.addProperty("hasDetails",                &Private::hasDetails);
5286         s_inst.addProperty("modules",                   &Private::modules);
5287         s_inst.addProperty("dirs",                      &Private::dirs);
5288         s_inst.addProperty("files",                     &Private::files);
5289         s_inst.addProperty("namespaces",                &Private::namespaces);
5290         s_inst.addProperty("classes",                   &Private::classes);
5291         s_inst.addProperty("constantgroups",            &Private::constantgroups);
5292         s_inst.addProperty("examples",                  &Private::examples);
5293         s_inst.addProperty("macros",                    &Private::macros);
5294         s_inst.addProperty("typedefs",                  &Private::typedefs);
5295         s_inst.addProperty("enums",                     &Private::enums);
5296         s_inst.addProperty("enumvalues",                &Private::enumValues);
5297         s_inst.addProperty("functions",                 &Private::functions);
5298         s_inst.addProperty("variables",                 &Private::variables);
5299         s_inst.addProperty("signals",                   &Private::signals);
5300         s_inst.addProperty("publicSlots",               &Private::publicSlots);
5301         s_inst.addProperty("protectedSlots",            &Private::protectedSlots);
5302         s_inst.addProperty("privateSlots",              &Private::privateSlots);
5303         s_inst.addProperty("events",                    &Private::events);
5304         s_inst.addProperty("properties",                &Private::properties);
5305         s_inst.addProperty("friends",                   &Private::friends);
5306         s_inst.addProperty("memberGroups",              &Private::memberGroups);
5307         s_inst.addProperty("detailedMacros",            &Private::detailedMacros);
5308         s_inst.addProperty("detailedTypedefs",          &Private::detailedTypedefs);
5309         s_inst.addProperty("detailedEnums",             &Private::detailedEnums);
5310         s_inst.addProperty("detailedEnumValues",        &Private::detailedEnumValues);
5311         s_inst.addProperty("detailedFunctions",         &Private::detailedFunctions);
5312         s_inst.addProperty("detailedVariables",         &Private::detailedVariables);
5313         s_inst.addProperty("detailedSignals",           &Private::detailedSignals);
5314         s_inst.addProperty("detailedPublicSlots",       &Private::detailedPublicSlots);
5315         s_inst.addProperty("detailedProtectedSlots",    &Private::detailedProtectedSlots);
5316         s_inst.addProperty("detailedPrivateSlots",      &Private::detailedPrivateSlots);
5317         s_inst.addProperty("detailedEvents",            &Private::detailedEvents);
5318         s_inst.addProperty("detailedProperties",        &Private::detailedProperties);
5319         s_inst.addProperty("detailedFriends",           &Private::detailedFriends);
5320         s_inst.addProperty("inlineClasses",             &Private::inlineClasses);
5321         s_inst.addProperty("compoundType",              &Private::compoundType);
5322         init=TRUE;
5323       }
5324       if (!gd->cookie()) { gd->setCookie(new ModuleContext::Private::Cachable(gd)); }
5325     }
5326     virtual ~Private() {}
5327     TemplateVariant get(const char *n) const
5328     {
5329       return s_inst.get(this,n);
5330     }
5331     TemplateVariant title() const
5332     {
5333       return TemplateVariant(m_groupDef->groupTitle());
5334     }
5335     TemplateVariant highlight() const
5336     {
5337       return TemplateVariant("modules");
5338     }
5339     TemplateVariant subHighlight() const
5340     {
5341       return TemplateVariant("");
5342     }
5343     DotGroupCollaboration *getGroupGraph() const
5344     {
5345       Cachable &cache = getCache();
5346       if (!cache.groupGraph)
5347       {
5348         cache.groupGraph.reset(new DotGroupCollaboration(m_groupDef));
5349       }
5350       return cache.groupGraph.get();
5351     }
5352     TemplateVariant hasGroupGraph() const
5353     {
5354       bool result=FALSE;
5355       static bool haveDot     = Config_getBool(HAVE_DOT);
5356       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
5357       if (haveDot && groupGraphs)
5358       {
5359         DotGroupCollaboration *graph = getGroupGraph();
5360         result = !graph->isTrivial();
5361       }
5362       return result;
5363     }
5364     TemplateVariant groupGraph() const
5365     {
5366       QGString result;
5367       static bool haveDot     = Config_getBool(HAVE_DOT);
5368       static bool groupGraphs = Config_getBool(GROUP_GRAPHS);
5369       if (haveDot && groupGraphs)
5370       {
5371         DotGroupCollaboration *graph = getGroupGraph();
5372         FTextStream t(&result);
5373         switch (g_globals.outputFormat)
5374         {
5375           case ContextOutputFormat_Html:
5376             {
5377               graph->writeGraph(t,GOF_BITMAP,
5378                                 EOF_Html,
5379                                 g_globals.outputDir,
5380                                 g_globals.outputDir+portable_pathSeparator()+m_groupDef->getOutputFileBase()+Doxygen::htmlFileExtension,
5381                                 relPathAsString(),
5382                                 TRUE,
5383                                 g_globals.dynSectionId);
5384             }
5385             break;
5386           case ContextOutputFormat_Latex:
5387             {
5388               graph->writeGraph(t,GOF_EPS,
5389                                 EOF_LaTeX,
5390                                 g_globals.outputDir,
5391                                 g_globals.outputDir+portable_pathSeparator()+m_groupDef->getOutputFileBase()+".tex",
5392                                 relPathAsString(),
5393                                 TRUE,
5394                                 g_globals.dynSectionId);
5395             }
5396             break;
5397             // TODO: support other generators
5398           default:
5399             err("context.cpp: output format not yet supported");
5400             break;
5401         }
5402         g_globals.dynSectionId++;
5403       }
5404       return TemplateVariant(result.data(),TRUE);
5405     }
5406     TemplateVariant hasDetails() const
5407     {
5408       return m_groupDef->hasDetailedDescription();
5409     }
5410     TemplateVariant modules() const
5411     {
5412       Cachable &cache = getCache();
5413       if (!cache.modules)
5414       {
5415         TemplateList *moduleList = TemplateList::alloc();
5416         if (m_groupDef->getSubGroups())
5417         {
5418           GroupListIterator gli(*m_groupDef->getSubGroups());
5419           GroupDef *gd;
5420           for (gli.toFirst();(gd=gli.current());++gli)
5421           {
5422             if (gd->isVisible())
5423             {
5424               moduleList->append(ModuleContext::alloc(gd));
5425             }
5426           }
5427         }
5428         cache.modules.reset(moduleList);
5429       }
5430       return cache.modules.get();
5431     }
5432     TemplateVariant examples() const
5433     {
5434       Cachable &cache = getCache();
5435       if (!cache.examples)
5436       {
5437         TemplateList *exampleList = TemplateList::alloc();
5438         if (m_groupDef->getExamples())
5439         {
5440           PageSDict::Iterator eli(*m_groupDef->getExamples());
5441           PageDef *ex;
5442           for (eli.toFirst();(ex=eli.current());++eli)
5443           {
5444             exampleList->append(PageContext::alloc(ex,FALSE,TRUE));
5445           }
5446         }
5447         cache.examples.reset(exampleList);
5448       }
5449       return cache.examples.get();
5450     }
5451     TemplateVariant pages() const
5452     {
5453       Cachable &cache = getCache();
5454       if (!cache.pages)
5455       {
5456         TemplateList *pageList = TemplateList::alloc();
5457         if (m_groupDef->getExamples())
5458         {
5459           PageSDict::Iterator eli(*m_groupDef->getPages());
5460           PageDef *ex;
5461           for (eli.toFirst();(ex=eli.current());++eli)
5462           {
5463             pageList->append(PageContext::alloc(ex,FALSE,TRUE));
5464           }
5465         }
5466         cache.pages.reset(pageList);
5467       }
5468       return cache.pages.get();
5469     }
5470     TemplateVariant dirs() const
5471     {
5472       Cachable &cache = getCache();
5473       if (!cache.dirs)
5474       {
5475         TemplateList *dirList = TemplateList::alloc();
5476         if (m_groupDef->getDirs())
5477         {
5478           QListIterator<DirDef> it(*m_groupDef->getDirs());
5479           DirDef *dd;
5480           for (it.toFirst();(dd=it.current());++it)
5481           {
5482             dirList->append(DirContext::alloc(dd));
5483           }
5484         }
5485         cache.dirs.reset(dirList);
5486       }
5487       return cache.dirs.get();
5488     }
5489     TemplateVariant files() const
5490     {
5491       Cachable &cache = getCache();
5492       if (!cache.files)
5493       {
5494         TemplateList *fileList = TemplateList::alloc();
5495         if (m_groupDef->getFiles())
5496         {
5497           QListIterator<FileDef> it(*m_groupDef->getFiles());
5498           FileDef *fd;
5499           for (it.toFirst();(fd=it.current());++it)
5500           {
5501             fileList->append(FileContext::alloc(fd));
5502           }
5503         }
5504         cache.files.reset(fileList);
5505       }
5506       return cache.files.get();
5507     }
5508     TemplateVariant classes() const
5509     {
5510       Cachable &cache = getCache();
5511       if (!cache.classes)
5512       {
5513         TemplateList *classList = TemplateList::alloc();
5514         if (m_groupDef->getClasses())
5515         {
5516           ClassSDict::Iterator sdi(*m_groupDef->getClasses());
5517           ClassDef *cd;
5518           for (sdi.toFirst();(cd=sdi.current());++sdi)
5519           {
5520             if (cd->visibleInParentsDeclList())
5521             {
5522               classList->append(ClassContext::alloc(cd));
5523             }
5524           }
5525         }
5526         cache.classes.reset(classList);
5527       }
5528       return cache.classes.get();
5529     }
5530     TemplateVariant namespaces() const
5531     {
5532       Cachable &cache = getCache();
5533       if (!cache.namespaces)
5534       {
5535         TemplateList *namespaceList = TemplateList::alloc();
5536         if (m_groupDef->getNamespaces())
5537         {
5538           NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces());
5539           NamespaceDef *nd;
5540           for (sdi.toFirst();(nd=sdi.current());++sdi)
5541           {
5542             if (nd->isLinkable() && !nd->isConstantGroup())
5543             {
5544               namespaceList->append(NamespaceContext::alloc(nd));
5545             }
5546           }
5547         }
5548         cache.namespaces.reset(namespaceList);
5549       }
5550       return cache.namespaces.get();
5551     }
5552     TemplateVariant constantgroups() const
5553     {
5554       Cachable &cache = getCache();
5555       if (!cache.constantgroups)
5556       {
5557         TemplateList *namespaceList = TemplateList::alloc();
5558         if (m_groupDef->getNamespaces())
5559         {
5560           NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces());
5561           NamespaceDef *nd;
5562           for (sdi.toFirst();(nd=sdi.current());++sdi)
5563           {
5564             if (nd->isLinkable() && nd->isConstantGroup())
5565             {
5566               namespaceList->append(NamespaceContext::alloc(nd));
5567             }
5568           }
5569         }
5570         cache.constantgroups.reset(namespaceList);
5571       }
5572       return cache.constantgroups.get();
5573     }
5574
5575     TemplateVariant getMemberList(SharedPtr<MemberListInfoContext> &list,
5576                                   MemberListType type,const char *title,bool detailed=FALSE) const
5577     {
5578       if (!list)
5579       {
5580         MemberList *ml = m_groupDef->getMemberList(type);
5581         if (ml)
5582         {
5583           list.reset(MemberListInfoContext::alloc(m_groupDef,relPathAsString(),ml,title,""));
5584         }
5585       }
5586       if (list)
5587       {
5588         return list.get();
5589       }
5590       else
5591       {
5592         return TemplateVariant(FALSE);
5593       }
5594     }
5595     TemplateVariant macros() const
5596     {
5597       return getMemberList(getCache().macros,MemberListType_decDefineMembers,theTranslator->trDefines());
5598     }
5599     TemplateVariant typedefs() const
5600     {
5601       return getMemberList(getCache().typedefs,MemberListType_decTypedefMembers,theTranslator->trTypedefs());
5602     }
5603     TemplateVariant enums() const
5604     {
5605       return getMemberList(getCache().enums,MemberListType_decEnumMembers,theTranslator->trEnumerations());
5606     }
5607     TemplateVariant enumValues() const
5608     {
5609       return getMemberList(getCache().enums,MemberListType_decEnumValMembers,theTranslator->trEnumerationValues());
5610     }
5611     TemplateVariant functions() const
5612     {
5613       QCString title = theTranslator->trFunctions();
5614       SrcLangExt lang = m_groupDef->getLanguage();
5615       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprograms();
5616       else if (lang==SrcLangExt_VHDL) title=theTranslator->trFunctionAndProc();
5617       return getMemberList(getCache().functions,MemberListType_decFuncMembers,title);
5618     }
5619     TemplateVariant variables() const
5620     {
5621       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
5622       return getMemberList(getCache().variables,MemberListType_decVarMembers,
5623                            sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables());
5624     }
5625     TemplateVariant signals() const
5626     {
5627       return getMemberList(getCache().signals,MemberListType_signals,theTranslator->trSignals());
5628     }
5629     TemplateVariant publicSlots() const
5630     {
5631       return getMemberList(getCache().publicSlots,MemberListType_pubSlots,theTranslator->trPublicSlots());
5632     }
5633     TemplateVariant protectedSlots() const
5634     {
5635       return getMemberList(getCache().protectedSlots,MemberListType_proSlots,theTranslator->trProtectedSlots());
5636     }
5637     TemplateVariant privateSlots() const
5638     {
5639       return getMemberList(getCache().privateSlots,MemberListType_priSlots,theTranslator->trPrivateSlots());
5640     }
5641     TemplateVariant events() const
5642     {
5643       return getMemberList(getCache().events,MemberListType_events,theTranslator->trEvents());
5644     }
5645     TemplateVariant properties() const
5646     {
5647       return getMemberList(getCache().properties,MemberListType_properties,theTranslator->trProperties());
5648     }
5649     TemplateVariant friends() const
5650     {
5651       return getMemberList(getCache().friends,MemberListType_friends,theTranslator->trFriends());
5652     }
5653     TemplateVariant memberGroups() const
5654     {
5655       Cachable &cache = getCache();
5656       if (!cache.memberGroups)
5657       {
5658         if (m_groupDef->getMemberGroupSDict())
5659         {
5660           cache.memberGroups.reset(MemberGroupListContext::alloc(m_groupDef,relPathAsString(),m_groupDef->getMemberGroupSDict(),m_groupDef->subGrouping()));
5661         }
5662         else
5663         {
5664           cache.memberGroups.reset(MemberGroupListContext::alloc());
5665         }
5666       }
5667       return cache.memberGroups.get();
5668     }
5669     TemplateVariant detailedMacros() const
5670     {
5671       return getMemberList(getCache().detailedMacros,MemberListType_docDefineMembers,theTranslator->trDefineDocumentation());
5672     }
5673     TemplateVariant detailedTypedefs() const
5674     {
5675       return getMemberList(getCache().detailedTypedefs,MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation());
5676     }
5677     TemplateVariant detailedEnums() const
5678     {
5679       return getMemberList(getCache().detailedEnums,MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation());
5680     }
5681     TemplateVariant detailedEnumValues() const
5682     {
5683       return getMemberList(getCache().detailedEnumValues,MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation());
5684     }
5685     TemplateVariant detailedFunctions() const
5686     {
5687       QCString title = theTranslator->trFunctionDocumentation();
5688       SrcLangExt lang = m_groupDef->getLanguage();
5689       if (lang==SrcLangExt_Fortran) title=theTranslator->trSubprogramDocumentation();
5690       return getMemberList(getCache().detailedFunctions,MemberListType_docFuncMembers,title);
5691     }
5692     TemplateVariant detailedVariables() const
5693     {
5694       return getMemberList(getCache().detailedVariables,MemberListType_docVarMembers,theTranslator->trVariableDocumentation());
5695     }
5696     TemplateVariant detailedSignals() const
5697     {
5698       return getMemberList(getCache().detailedSignals,MemberListType_docSignalMembers,theTranslator->trSignals());
5699     }
5700     TemplateVariant detailedPublicSlots() const
5701     {
5702       return getMemberList(getCache().detailedPublicSlots,MemberListType_docPubSlotMembers,theTranslator->trPublicSlots());
5703     }
5704     TemplateVariant detailedProtectedSlots() const
5705     {
5706       return getMemberList(getCache().detailedProtectedSlots,MemberListType_docProSlotMembers,theTranslator->trProtectedSlots());
5707     }
5708     TemplateVariant detailedPrivateSlots() const
5709     {
5710       return getMemberList(getCache().detailedPrivateSlots,MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots());
5711     }
5712     TemplateVariant detailedEvents() const
5713     {
5714       return getMemberList(getCache().detailedEvents,MemberListType_docEventMembers,theTranslator->trEventDocumentation(),TRUE);
5715     }
5716     TemplateVariant detailedProperties() const
5717     {
5718       return getMemberList(getCache().detailedProperties,MemberListType_docPropMembers,theTranslator->trPropertyDocumentation(),TRUE);
5719     }
5720     TemplateVariant detailedFriends() const
5721     {
5722       return getMemberList(getCache().detailedFriends,MemberListType_docFriendMembers,theTranslator->trFriends(),TRUE);
5723     }
5724     TemplateVariant inlineClasses() const
5725     {
5726       Cachable &cache = getCache();
5727       if (!cache.inlineClasses)
5728       {
5729         TemplateList *classList = TemplateList::alloc();
5730         if (m_groupDef->getClasses())
5731         {
5732           ClassSDict::Iterator sdi(*m_groupDef->getClasses());
5733           ClassDef *cd;
5734           for (sdi.toFirst();(cd=sdi.current());++sdi)
5735           {
5736             if (cd->name().find('@')==-1 &&
5737                 cd->isLinkableInProject() &&
5738                 cd->isEmbeddedInOuterScope() &&
5739                 cd->partOfGroups()==0)
5740             {
5741               classList->append(ClassContext::alloc(cd));
5742             }
5743           }
5744         }
5745         cache.inlineClasses.reset(classList);
5746       }
5747       return cache.inlineClasses.get();
5748     }
5749     TemplateVariant compoundType() const
5750     {
5751       return "module"; //theTranslator->trGroup(FALSE,TRUE);
5752     }
5753   private:
5754     GroupDef *m_groupDef;
5755     struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable
5756     {
5757       Cachable(GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {}
5758       SharedPtr<TemplateList>               modules;
5759       SharedPtr<TemplateList>               dirs;
5760       SharedPtr<TemplateList>               files;
5761       SharedPtr<TemplateList>               classes;
5762       SharedPtr<TemplateList>               namespaces;
5763       SharedPtr<TemplateList>               constantgroups;
5764       SharedPtr<TemplateList>               examples;
5765       SharedPtr<TemplateList>               pages;
5766       SharedPtr<MemberListInfoContext>      macros;
5767       SharedPtr<MemberListInfoContext>      typedefs;
5768       SharedPtr<MemberListInfoContext>      enums;
5769       SharedPtr<MemberListInfoContext>      enumValues;
5770       SharedPtr<MemberListInfoContext>      functions;
5771       SharedPtr<MemberListInfoContext>      variables;
5772       SharedPtr<MemberListInfoContext>      signals;
5773       SharedPtr<MemberListInfoContext>      publicSlots;
5774       SharedPtr<MemberListInfoContext>      protectedSlots;
5775       SharedPtr<MemberListInfoContext>      privateSlots;
5776       SharedPtr<MemberListInfoContext>      events;
5777       SharedPtr<MemberListInfoContext>      properties;
5778       SharedPtr<MemberListInfoContext>      friends;
5779       SharedPtr<MemberGroupListContext>     memberGroups;
5780       SharedPtr<MemberListInfoContext>      detailedMacros;
5781       SharedPtr<MemberListInfoContext>      detailedTypedefs;
5782       SharedPtr<MemberListInfoContext>      detailedEnums;
5783       SharedPtr<MemberListInfoContext>      detailedEnumValues;
5784       SharedPtr<MemberListInfoContext>      detailedFunctions;
5785       SharedPtr<MemberListInfoContext>      detailedVariables;
5786       SharedPtr<MemberListInfoContext>      detailedSignals;
5787       SharedPtr<MemberListInfoContext>      detailedPublicSlots;
5788       SharedPtr<MemberListInfoContext>      detailedProtectedSlots;
5789       SharedPtr<MemberListInfoContext>      detailedPrivateSlots;
5790       SharedPtr<MemberListInfoContext>      detailedEvents;
5791       SharedPtr<MemberListInfoContext>      detailedProperties;
5792       SharedPtr<MemberListInfoContext>      detailedFriends;
5793       SharedPtr<TemplateList>               inlineClasses;
5794       ScopedPtr<DotGroupCollaboration>      groupGraph;
5795     };
5796     Cachable &getCache() const
5797     {
5798       Cachable *c = static_cast<Cachable*>(m_groupDef->cookie());
5799       assert(c!=0);
5800       return *c;
5801     }
5802     static PropertyMapper<ModuleContext::Private> s_inst;
5803 };
5804 //%% }
5805
5806 PropertyMapper<ModuleContext::Private> ModuleContext::Private::s_inst;
5807
5808 ModuleContext::ModuleContext(GroupDef *gd) : RefCountedContext("ModuleContext")
5809 {
5810   p = new Private(gd);
5811 }
5812
5813 ModuleContext::~ModuleContext()
5814 {
5815   delete p;
5816 }
5817
5818 TemplateVariant ModuleContext::get(const char *n) const
5819 {
5820   return p->get(n);
5821 }
5822
5823 //------------------------------------------------------------------------
5824
5825 //%% list ClassList[Class] : list of classes
5826 class ClassListContext::Private : public GenericNodeListContext
5827 {
5828   public:
5829     void addClasses(const ClassSDict &classSDict)
5830     {
5831       ClassSDict::Iterator cli(classSDict);
5832       ClassDef *cd;
5833       for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
5834       {
5835         if (cd->getLanguage()==SrcLangExt_VHDL &&
5836             ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
5837              (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
5838            ) // no architecture
5839         {
5840           continue;
5841         }
5842         if (cd->isLinkableInProject() && cd->templateMaster()==0 &&
5843             !cd->isHidden() && !cd->isEmbeddedInOuterScope())
5844         {
5845           append(ClassContext::alloc(cd));
5846         }
5847       }
5848     }
5849 };
5850
5851 ClassListContext::ClassListContext() : RefCountedContext("ClassListContext")
5852 {
5853   p = new Private;
5854   p->addClasses(*Doxygen::classSDict);
5855   p->addClasses(*Doxygen::hiddenClasses);
5856 }
5857
5858 ClassListContext::~ClassListContext()
5859 {
5860   delete p;
5861 }
5862
5863 // TemplateListIntf
5864 int ClassListContext::count() const
5865 {
5866   return p->count();
5867 }
5868
5869 TemplateVariant ClassListContext::at(int index) const
5870 {
5871   return p->at(index);
5872 }
5873
5874 TemplateListIntf::ConstIterator *ClassListContext::createIterator() const
5875 {
5876   return p->createIterator();
5877 }
5878
5879 //------------------------------------------------------------------------
5880
5881 //%% list ClassIndex[Class] : list of classes
5882 class ClassIndexContext::Private
5883 {
5884   public:
5885     Private()
5886     {
5887       static bool init=FALSE;
5888       if (!init)
5889       {
5890         s_inst.addProperty("list",        &Private::list);
5891         s_inst.addProperty("fileName",    &Private::fileName);
5892         s_inst.addProperty("relPath",     &Private::relPath);
5893         s_inst.addProperty("highlight",   &Private::highlight);
5894         s_inst.addProperty("subhighlight",&Private::subhighlight);
5895         s_inst.addProperty("title",       &Private::title);
5896         init=TRUE;
5897       }
5898     }
5899     TemplateVariant get(const char *n) const
5900     {
5901       return s_inst.get(this,n);
5902     }
5903     TemplateVariant list() const
5904     {
5905       if (!m_cache.classes)
5906       {
5907         TemplateList *classList = TemplateList::alloc();
5908         if (Doxygen::classSDict)
5909         {
5910           ClassSDict::Iterator cli(*Doxygen::classSDict);
5911           ClassDef *cd;
5912           for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
5913           {
5914             if (cd->getLanguage()==SrcLangExt_VHDL &&
5915                 ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
5916                  (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
5917                ) // no architecture
5918             {
5919               continue;
5920             }
5921             if (cd->isLinkableInProject() && cd->templateMaster()==0)
5922             {
5923               classList->append(ClassContext::alloc(cd));
5924             }
5925           }
5926         }
5927         m_cache.classes.reset(classList);
5928       }
5929       return m_cache.classes.get();
5930     }
5931     TemplateVariant fileName() const
5932     {
5933       return "classes";
5934     }
5935     TemplateVariant relPath() const
5936     {
5937       return "";
5938     }
5939     TemplateVariant highlight() const
5940     {
5941       return "classes";
5942     }
5943     TemplateVariant subhighlight() const
5944     {
5945       return "classindex";
5946     }
5947     TemplateVariant title() const
5948     {
5949       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
5950       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
5951       if (fortranOpt)
5952       {
5953         return theTranslator->trDataTypes();
5954       }
5955       else if (vhdlOpt)
5956       {
5957         return theTranslator->trDesignUnits();
5958       }
5959       else
5960       {
5961         return theTranslator->trCompoundIndex();
5962       }
5963     }
5964   private:
5965     struct Cachable
5966     {
5967       SharedPtr<TemplateList> classes;
5968     };
5969     mutable Cachable m_cache;
5970     static PropertyMapper<ClassIndexContext::Private> s_inst;
5971 };
5972
5973 PropertyMapper<ClassIndexContext::Private> ClassIndexContext::Private::s_inst;
5974
5975 ClassIndexContext::ClassIndexContext() : RefCountedContext("ClassIndexContext")
5976 {
5977   p = new Private;
5978   //p->addClasses(*Doxygen::hiddenClasses);
5979 }
5980
5981 ClassIndexContext::~ClassIndexContext()
5982 {
5983   delete p;
5984 }
5985
5986 // TemplateStructIntf
5987 TemplateVariant ClassIndexContext::get(const char *n) const
5988 {
5989   return p->get(n);
5990 }
5991
5992 //------------------------------------------------------------------------
5993
5994 static int computeMaxDepth(const TemplateListIntf *list)
5995 {
5996   int maxDepth=0;
5997   if (list)
5998   {
5999     TemplateListIntf::ConstIterator *it = list->createIterator();
6000     TemplateVariant v;
6001     for (it->toFirst();it->current(v);it->toNext())
6002     {
6003       const TemplateStructIntf *s = v.toStruct();
6004       TemplateVariant child = s->get("children");
6005       int d = computeMaxDepth(child.toList())+1;
6006       if (d>maxDepth) maxDepth=d;
6007     }
6008     delete it;
6009   }
6010   return maxDepth;
6011 }
6012
6013 static int computeNumNodesAtLevel(const TemplateStructIntf *s,int level,int maxLevel)
6014 {
6015   int num=0;
6016   if (level<maxLevel)
6017   {
6018     num++;
6019     TemplateVariant child = s->get("children");
6020     if (child.toList())
6021     {
6022       TemplateListIntf::ConstIterator *it = child.toList()->createIterator();
6023       TemplateVariant v;
6024       for (it->toFirst();it->current(v);it->toNext())
6025       {
6026         num+=computeNumNodesAtLevel(v.toStruct(),level+1,maxLevel);
6027       }
6028       delete it;
6029     }
6030   }
6031   return num;
6032 }
6033
6034 static int computePreferredDepth(const TemplateListIntf *list,int maxDepth)
6035 {
6036   int preferredNumEntries = Config_getInt(HTML_INDEX_NUM_ENTRIES);
6037   int preferredDepth=1;
6038   if (preferredNumEntries>0)
6039   {
6040     int depth = maxDepth;
6041     for (int i=1;i<=depth;i++)
6042     {
6043       int num=0;
6044       TemplateListIntf::ConstIterator *it = list->createIterator();
6045       TemplateVariant v;
6046       for (it->toFirst();it->current(v);it->toNext())
6047       {
6048         num+=computeNumNodesAtLevel(v.toStruct(),0,i);
6049       }
6050       delete it;
6051       if (num<=preferredNumEntries)
6052       {
6053         preferredDepth=i;
6054       }
6055       else
6056       {
6057         break;
6058       }
6059     }
6060   }
6061   return preferredDepth;
6062 }
6063
6064 //------------------------------------------------------------------------
6065
6066 //%% struct ClassHierarchy: inheritance tree
6067 //%% {
6068 class ClassHierarchyContext::Private
6069 {
6070   public:
6071     Private()
6072     {
6073       m_classTree.reset(NestingContext::alloc(0,0));
6074       initClassHierarchy(Doxygen::classSDict);
6075       initClassHierarchy(Doxygen::hiddenClasses);
6076       m_classTree->addClassHierarchy(*Doxygen::classSDict,TRUE);
6077       m_classTree->addClassHierarchy(*Doxygen::hiddenClasses,TRUE);
6078       //%% ClassInheritance tree
6079       static bool init=FALSE;
6080       if (!init)
6081       {
6082         s_inst.addProperty("tree",            &Private::tree);
6083         s_inst.addProperty("fileName",        &Private::fileName);
6084         s_inst.addProperty("relPath",         &Private::relPath);
6085         s_inst.addProperty("highlight",       &Private::highlight);
6086         s_inst.addProperty("subhighlight",    &Private::subhighlight);
6087         s_inst.addProperty("title",           &Private::title);
6088         s_inst.addProperty("preferredDepth",  &Private::preferredDepth);
6089         s_inst.addProperty("maxDepth",        &Private::maxDepth);
6090         s_inst.addProperty("diagrams",        &Private::diagrams);
6091         init=TRUE;
6092       }
6093     }
6094     TemplateVariant get(const char *n) const
6095     {
6096       return s_inst.get(this,n);
6097     }
6098     TemplateVariant tree() const
6099     {
6100       return m_classTree.get();
6101     }
6102     TemplateVariant fileName() const
6103     {
6104       return "hierarchy";
6105     }
6106     TemplateVariant relPath() const
6107     {
6108       return "";
6109     }
6110     TemplateVariant highlight() const
6111     {
6112       return "classes";
6113     }
6114     TemplateVariant subhighlight() const
6115     {
6116       return "classhierarchy";
6117     }
6118     DotGfxHierarchyTable *getHierarchy() const
6119     {
6120       if (!m_cache.hierarchy)
6121       {
6122         m_cache.hierarchy.reset(new DotGfxHierarchyTable());
6123       }
6124       return m_cache.hierarchy.get();
6125     }
6126     TemplateVariant diagrams() const
6127     {
6128       if (!m_cache.diagrams)
6129       {
6130         TemplateList *diagrams = TemplateList::alloc();
6131         DotGfxHierarchyTable *hierarchy = getHierarchy();
6132         if (hierarchy->subGraphs())
6133         {
6134           int id=0;
6135           QListIterator<DotNode> li(*hierarchy->subGraphs());
6136           DotNode *n;
6137           for (li.toFirst();(n=li.current());++li)
6138           {
6139             diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++));
6140           }
6141         }
6142         m_cache.diagrams.reset(diagrams);
6143       }
6144       return m_cache.diagrams.get();
6145     }
6146     TemplateVariant title() const
6147     {
6148       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
6149       if (vhdlOpt)
6150       {
6151         return theTranslator->trDesignUnitHierarchy();
6152       }
6153       else
6154       {
6155         return theTranslator->trClassHierarchy();
6156       }
6157     }
6158     TemplateVariant maxDepth() const
6159     {
6160       if (!m_cache.maxDepthComputed)
6161       {
6162         m_cache.maxDepth = computeMaxDepth(m_classTree.get());
6163         m_cache.maxDepthComputed=TRUE;
6164       }
6165       return m_cache.maxDepth;
6166     }
6167     TemplateVariant preferredDepth() const
6168     {
6169       if (!m_cache.preferredDepthComputed)
6170       {
6171         m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt());
6172         m_cache.preferredDepthComputed=TRUE;
6173       }
6174       return m_cache.preferredDepth;
6175     }
6176   private:
6177     SharedPtr<NestingContext> m_classTree;
6178     struct Cachable
6179     {
6180       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
6181                    preferredDepth(0), preferredDepthComputed(FALSE), hierarchy(0) {}
6182       int   maxDepth;
6183       bool  maxDepthComputed;
6184       int   preferredDepth;
6185       bool  preferredDepthComputed;
6186       SharedPtr<TemplateList> diagrams;
6187       ScopedPtr<DotGfxHierarchyTable> hierarchy;
6188     };
6189     mutable Cachable m_cache;
6190     static PropertyMapper<ClassHierarchyContext::Private> s_inst;
6191 };
6192 //%% }
6193
6194 PropertyMapper<ClassHierarchyContext::Private> ClassHierarchyContext::Private::s_inst;
6195
6196 ClassHierarchyContext::ClassHierarchyContext() : RefCountedContext("ClassHierarchyContext")
6197 {
6198   p = new Private;
6199 }
6200
6201 ClassHierarchyContext::~ClassHierarchyContext()
6202 {
6203   delete p;
6204 }
6205
6206 TemplateVariant ClassHierarchyContext::get(const char *name) const
6207 {
6208   return p->get(name);
6209 }
6210
6211 //------------------------------------------------------------------------
6212
6213 //%% struct NestingNode: node is a nesting relation tree
6214 //%% {
6215 class NestingNodeContext::Private
6216 {
6217   public:
6218     Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode,
6219         Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper)
6220       : m_parent(parent), m_def(d), m_level(level), m_index(index)
6221     {
6222       m_children.reset(NestingContext::alloc(thisNode,level+1));
6223       static bool init=FALSE;
6224       if (!init)
6225       {
6226         //%% bool is_leaf_node: true if this node does not have any children
6227         s_inst.addProperty("is_leaf_node",&Private::isLeafNode);
6228         //%% Nesting children: list of nested classes/namespaces
6229         s_inst.addProperty("children",&Private::children);
6230         //%% [optional] Class class: class info (if this node represents a class)
6231         s_inst.addProperty("class",&Private::getClass);
6232         //%% [optional] Namespace namespace: namespace info (if this node represents a namespace)
6233         s_inst.addProperty("namespace",&Private::getNamespace);
6234         //%% [optional] File file: file info (if this node represents a file)
6235         s_inst.addProperty("file",&Private::getFile);
6236         //%% [optional] Dir dir: directory info (if this node represents a directory)
6237         s_inst.addProperty("dir",&Private::getDir);
6238         //%% [optional] Page page: page info (if this node represents a page)
6239         s_inst.addProperty("page",&Private::getPage);
6240         //%% [optional] Module module: module info (if this node represents a module)
6241         s_inst.addProperty("module",&Private::getModule);
6242         //%% int id
6243         s_inst.addProperty("id",&Private::id);
6244         //%% string level
6245         s_inst.addProperty("level",&Private::level);
6246         //%% string name
6247         s_inst.addProperty("name",&Private::name);
6248         //%% string brief
6249         s_inst.addProperty("brief",&Private::brief);
6250         //%% bool isLinkable
6251         s_inst.addProperty("isLinkable",&Private::isLinkable);
6252         s_inst.addProperty("anchor",&Private::anchor);
6253         s_inst.addProperty("fileName",&Private::fileName);
6254         s_inst.addProperty("isReference",&Private::isReference);
6255         s_inst.addProperty("externalReference",&Private::externalReference);
6256         init=TRUE;
6257       }
6258
6259       addNamespaces(addCls);
6260       addClasses(inherit,hideSuper);
6261       addDirFiles();
6262       addPages();
6263       addModules();
6264     }
6265     TemplateVariant get(const char *n) const
6266     {
6267       return s_inst.get(this,n);
6268     }
6269     TemplateVariant isLeafNode() const
6270     {
6271       return m_children->count()==0;
6272     }
6273     TemplateVariant children() const
6274     {
6275       return m_children.get();
6276     }
6277     TemplateVariant getClass() const
6278     {
6279       if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass)
6280       {
6281         m_cache.classContext.reset(ClassContext::alloc((ClassDef*)m_def));
6282       }
6283       if (m_cache.classContext)
6284       {
6285         return m_cache.classContext.get();
6286       }
6287       else
6288       {
6289         return TemplateVariant(FALSE);
6290       }
6291     }
6292     TemplateVariant getNamespace() const
6293     {
6294       if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace)
6295       {
6296         m_cache.namespaceContext.reset(NamespaceContext::alloc((NamespaceDef*)m_def));
6297       }
6298       if (m_cache.namespaceContext)
6299       {
6300         return m_cache.namespaceContext.get();
6301       }
6302       else
6303       {
6304         return TemplateVariant(FALSE);
6305       }
6306     }
6307     TemplateVariant getDir() const
6308     {
6309       if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir)
6310       {
6311         m_cache.dirContext.reset(DirContext::alloc((DirDef*)m_def));
6312       }
6313       if (m_cache.dirContext)
6314       {
6315         return m_cache.dirContext.get();
6316       }
6317       else
6318       {
6319         return TemplateVariant(FALSE);
6320       }
6321     }
6322     TemplateVariant getFile() const
6323     {
6324       if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile)
6325       {
6326         m_cache.fileContext.reset(FileContext::alloc((FileDef*)m_def));
6327       }
6328       if (m_cache.fileContext)
6329       {
6330         return m_cache.fileContext.get();
6331       }
6332       else
6333       {
6334         return TemplateVariant(FALSE);
6335       }
6336     }
6337     TemplateVariant getPage() const
6338     {
6339       if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage)
6340       {
6341         m_cache.pageContext.reset(PageContext::alloc((PageDef*)m_def,FALSE,FALSE));
6342       }
6343       if (m_cache.pageContext)
6344       {
6345         return m_cache.pageContext.get();
6346       }
6347       else
6348       {
6349         return TemplateVariant(FALSE);
6350       }
6351     }
6352     TemplateVariant getModule() const
6353     {
6354       if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup)
6355       {
6356         m_cache.moduleContext.reset(ModuleContext::alloc((GroupDef*)m_def));
6357       }
6358       if (m_cache.moduleContext)
6359       {
6360         return m_cache.moduleContext.get();
6361       }
6362       else
6363       {
6364         return TemplateVariant(FALSE);
6365       }
6366     }
6367     TemplateVariant level() const
6368     {
6369       return m_level;
6370     }
6371     TemplateVariant id() const
6372     {
6373       QCString result;
6374       if (m_parent) result=m_parent->id();
6375       result+=QCString().setNum(m_index)+"_";
6376       return result;
6377     }
6378     TemplateVariant name() const
6379     {
6380       return m_def->displayName(FALSE);
6381     }
6382     QCString relPathAsString() const
6383     {
6384       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
6385       return createSubdirs ? QCString("../../") : QCString("");
6386     }
6387     TemplateVariant brief() const
6388     {
6389       if (!m_cache.brief)
6390       {
6391         if (m_def->hasBriefDescription())
6392         {
6393           m_cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
6394                               "",m_def->briefDescription(),TRUE)));
6395         }
6396         else
6397         {
6398           m_cache.brief.reset(new TemplateVariant(""));
6399         }
6400       }
6401       return *m_cache.brief;
6402     }
6403     TemplateVariant isLinkable() const
6404     {
6405       return m_def->isLinkable();
6406     }
6407     TemplateVariant anchor() const
6408     {
6409       return m_def->anchor();
6410     }
6411     TemplateVariant fileName() const
6412     {
6413       return m_def->getOutputFileBase();
6414     }
6415     TemplateVariant isReference() const
6416     {
6417       return m_def->isReference();
6418     }
6419     TemplateVariant externalReference() const
6420     {
6421       return m_def->externalReference(relPathAsString());
6422     }
6423
6424     //------------------------------------------------------------------
6425
6426     void addClasses(bool inherit, bool hideSuper)
6427     {
6428       ClassDef *cd = m_def->definitionType()==Definition::TypeClass ? (ClassDef*)m_def : 0;
6429       if (cd && inherit)
6430       {
6431         bool hasChildren = !cd->visited && !hideSuper && classHasVisibleChildren(cd);
6432         if (hasChildren)
6433         {
6434           bool wasVisited=cd->visited;
6435           cd->visited=TRUE;
6436           if (cd->getLanguage()==SrcLangExt_VHDL)
6437           {
6438             m_children->addDerivedClasses(cd->baseClasses(),wasVisited);
6439           }
6440           else
6441           {
6442             m_children->addDerivedClasses(cd->subClasses(),wasVisited);
6443           }
6444         }
6445       }
6446       else
6447       {
6448         if (cd && cd->getClassSDict())
6449         {
6450           m_children->addClasses(*cd->getClassSDict(),FALSE);
6451         }
6452       }
6453     }
6454     void addNamespaces(bool addClasses)
6455     {
6456       NamespaceDef *nd = m_def->definitionType()==Definition::TypeNamespace ? (NamespaceDef*)m_def : 0;
6457       if (nd && nd->getNamespaceSDict())
6458       {
6459         m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses);
6460       }
6461       if (addClasses && nd && nd->getClassSDict())
6462       {
6463         m_children->addClasses(*nd->getClassSDict(),FALSE);
6464       }
6465     }
6466     void addDirFiles()
6467     {
6468       DirDef *dd = m_def->definitionType()==Definition::TypeDir ? (DirDef*)m_def : 0;
6469       if (dd)
6470       {
6471         m_children->addDirs(dd->subDirs());
6472         if (dd && dd->getFiles())
6473         {
6474           m_children->addFiles(*dd->getFiles());
6475         }
6476       }
6477     }
6478     void addPages()
6479     {
6480       PageDef *pd = m_def->definitionType()==Definition::TypePage ? (PageDef*)m_def : 0;
6481       if (pd && pd->getSubPages())
6482       {
6483         m_children->addPages(*pd->getSubPages(),FALSE);
6484       }
6485     }
6486     void addModules()
6487     {
6488       GroupDef *gd = m_def->definitionType()==Definition::TypeGroup ? (GroupDef*)m_def : 0;
6489       if (gd && gd->getSubGroups())
6490       {
6491         m_children->addModules(*gd->getSubGroups());
6492       }
6493     }
6494   private:
6495     const NestingNodeContext *m_parent;
6496     Definition *m_def;
6497     SharedPtr<NestingContext> m_children;
6498     int m_level;
6499     int m_index;
6500     struct Cachable
6501     {
6502       SharedPtr<ClassContext>     classContext;
6503       SharedPtr<NamespaceContext> namespaceContext;
6504       SharedPtr<DirContext>       dirContext;
6505       SharedPtr<FileContext>      fileContext;
6506       SharedPtr<PageContext>      pageContext;
6507       SharedPtr<ModuleContext>    moduleContext;
6508       ScopedPtr<TemplateVariant>  brief;
6509     };
6510     mutable Cachable m_cache;
6511     static PropertyMapper<NestingNodeContext::Private> s_inst;
6512 };
6513 //%% }
6514
6515 PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst;
6516
6517 NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
6518                                        Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper)
6519    : RefCountedContext("NestingNodeContext")
6520 {
6521   p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper);
6522 }
6523
6524 NestingNodeContext::~NestingNodeContext()
6525 {
6526   delete p;
6527 }
6528
6529 TemplateVariant NestingNodeContext::get(const char *n) const
6530 {
6531   return p->get(n);
6532 }
6533
6534 QCString NestingNodeContext::id() const
6535 {
6536   return p->id().toString();
6537 }
6538
6539 //------------------------------------------------------------------------
6540
6541 //%% list Nesting[NestingNode]: namespace and class nesting relations
6542 class NestingContext::Private : public GenericNodeListContext
6543 {
6544   public:
6545     Private(const NestingNodeContext *parent,int level)
6546       : m_parent(parent), m_level(level), m_index(0) {}
6547
6548     void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses)
6549     {
6550       NamespaceSDict::Iterator nli(nsDict);
6551       NamespaceDef *nd;
6552       for (nli.toFirst();(nd=nli.current());++nli)
6553       {
6554         if (nd->localName().find('@')==-1 &&
6555             (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
6556         {
6557           bool hasChildren = namespaceHasVisibleChild(nd,addClasses,false,ClassDef::Class);
6558           bool isLinkable  = nd->isLinkableInProject();
6559           if (isLinkable || hasChildren)
6560           {
6561             NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE);
6562             append(nnc);
6563             m_index++;
6564           }
6565         }
6566       }
6567     }
6568     void addClasses(const ClassSDict &clDict,bool rootOnly)
6569     {
6570       ClassSDict::Iterator cli(clDict);
6571       ClassDef *cd;
6572       for (;(cd=cli.current());++cli)
6573       {
6574         if (cd->getLanguage()==SrcLangExt_VHDL)
6575         {
6576           if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
6577               (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS
6578              )// no architecture
6579           {
6580             continue;
6581           }
6582         }
6583         if (!rootOnly ||
6584             cd->getOuterScope()==0 ||
6585             cd->getOuterScope()==Doxygen::globalScope
6586            )
6587         {
6588           if (classVisibleInIndex(cd) && cd->templateMaster()==0)
6589           {
6590             NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE);
6591             append(nnc);
6592             m_index++;
6593           }
6594         }
6595       }
6596     }
6597     void addDirs(const DirSDict &dirDict)
6598     {
6599       SDict<DirDef>::Iterator dli(dirDict);
6600       DirDef *dd;
6601       for (dli.toFirst();(dd=dli.current());++dli)
6602       {
6603         if (dd->getOuterScope()==Doxygen::globalScope)
6604         {
6605           append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE));
6606           m_index++;
6607         }
6608       }
6609     }
6610     void addDirs(const DirList &dirList)
6611     {
6612       QListIterator<DirDef> li(dirList);
6613       DirDef *dd;
6614       for (li.toFirst();(dd=li.current());++li)
6615       {
6616         append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE));
6617         m_index++;
6618       }
6619     }
6620     void addFiles(const FileNameList &fnList)
6621     {
6622       FileNameListIterator fnli(fnList);
6623       FileName *fn;
6624       for (fnli.toFirst();(fn=fnli.current());++fnli)
6625       {
6626         FileNameIterator fni(*fn);
6627         FileDef *fd;
6628         for (;(fd=fni.current());++fni)
6629         {
6630           if (fd->getDirDef()==0) // top level file
6631           {
6632             append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE));
6633             m_index++;
6634           }
6635         }
6636       }
6637     }
6638     void addFiles(const FileList &fList)
6639     {
6640       QListIterator<FileDef> li(fList);
6641       FileDef *fd;
6642       for (li.toFirst();(fd=li.current());++li)
6643       {
6644         append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE));
6645         m_index++;
6646       }
6647     }
6648     void addPages(const PageSDict &pages,bool rootOnly)
6649     {
6650       SDict<PageDef>::Iterator pli(pages);
6651       PageDef *pd;
6652       for (pli.toFirst();(pd=pli.current());++pli)
6653       {
6654         if (!rootOnly ||
6655             pd->getOuterScope()==0 ||
6656             pd->getOuterScope()->definitionType()!=Definition::TypePage)
6657         {
6658           append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE));
6659           m_index++;
6660         }
6661       }
6662     }
6663     void addModules(const GroupSDict &groups)
6664     {
6665       GroupSDict::Iterator gli(groups);
6666       GroupDef *gd;
6667       for (gli.toFirst();(gd=gli.current());++gli)
6668       {
6669         static bool externalGroups = Config_getBool(EXTERNAL_GROUPS);
6670         if (!gd->isASubGroup() && gd->isVisible() &&
6671              (!gd->isReference() || externalGroups)
6672            )
6673         {
6674           append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE));
6675           m_index++;
6676         }
6677       }
6678     }
6679     void addModules(const GroupList &list)
6680     {
6681       GroupListIterator gli(list);
6682       GroupDef *gd;
6683       for (gli.toFirst();(gd=gli.current());++gli)
6684       {
6685         if (gd->isVisible())
6686         {
6687           append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE));
6688           m_index++;
6689         }
6690       }
6691     }
6692     void addDerivedClasses(const BaseClassList *bcl,bool hideSuper)
6693     {
6694       if (bcl==0) return;
6695       BaseClassListIterator bcli(*bcl);
6696       BaseClassDef *bcd;
6697       for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli)
6698       {
6699         ClassDef *cd=bcd->classDef;
6700         if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
6701         {
6702           continue;
6703         }
6704
6705         bool b;
6706         if (cd->getLanguage()==SrcLangExt_VHDL)
6707         {
6708           b=hasVisibleRoot(cd->subClasses());
6709         }
6710         else
6711         {
6712           b=hasVisibleRoot(cd->baseClasses());
6713         }
6714
6715         if (cd->isVisibleInHierarchy() && b)
6716         {
6717           NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper);
6718           append(tnc);
6719           m_index++;
6720         }
6721       }
6722     }
6723     void addClassHierarchy(const ClassSDict &classSDict,bool)
6724     {
6725       ClassSDict::Iterator cli(classSDict);
6726       ClassDef *cd;
6727       for (cli.toFirst();(cd=cli.current());++cli)
6728       {
6729         bool b;
6730         if (cd->getLanguage()==SrcLangExt_VHDL)
6731         {
6732           if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
6733           {
6734             continue;
6735           }
6736           b=!hasVisibleRoot(cd->subClasses());
6737         }
6738         else
6739         {
6740           b=!hasVisibleRoot(cd->baseClasses());
6741         }
6742         if (b)
6743         {
6744           if (cd->isVisibleInHierarchy()) // should it be visible
6745           {
6746             // new root level class
6747             NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,cd->visited);
6748             append(nnc);
6749             m_index++;
6750           }
6751         }
6752       }
6753     }
6754
6755   private:
6756     const NestingNodeContext *m_parent;
6757     int m_level;
6758     int m_index;
6759 };
6760
6761 NestingContext::NestingContext(const NestingNodeContext *parent,int level) : RefCountedContext("NestingContext")
6762 {
6763   p = new Private(parent,level);
6764 }
6765
6766 NestingContext::~NestingContext()
6767 {
6768   delete p;
6769 }
6770
6771 // TemplateListIntf
6772 int NestingContext::count() const
6773 {
6774   return p->count();
6775 }
6776
6777 TemplateVariant NestingContext::at(int index) const
6778 {
6779   return p->at(index);
6780 }
6781
6782 TemplateListIntf::ConstIterator *NestingContext::createIterator() const
6783 {
6784   return p->createIterator();
6785 }
6786
6787 void NestingContext::addClasses(const ClassSDict &clDict,bool rootOnly)
6788 {
6789   p->addClasses(clDict,rootOnly);
6790 }
6791
6792 void NestingContext::addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses)
6793 {
6794   p->addNamespaces(nsDict,rootOnly,addClasses);
6795 }
6796
6797 void NestingContext::addDirs(const DirSDict &dirs)
6798 {
6799   p->addDirs(dirs);
6800 }
6801
6802 void NestingContext::addDirs(const DirList &dirs)
6803 {
6804   p->addDirs(dirs);
6805 }
6806
6807 void NestingContext::addFiles(const FileNameList &files)
6808 {
6809   p->addFiles(files);
6810 }
6811
6812 void NestingContext::addFiles(const FileList &files)
6813 {
6814   p->addFiles(files);
6815 }
6816
6817 void NestingContext::addPages(const PageSDict &pages,bool rootOnly)
6818 {
6819   p->addPages(pages,rootOnly);
6820 }
6821
6822 void NestingContext::addModules(const GroupSDict &modules)
6823 {
6824   p->addModules(modules);
6825 }
6826
6827 void NestingContext::addModules(const GroupList &modules)
6828 {
6829   p->addModules(modules);
6830 }
6831
6832 void NestingContext::addClassHierarchy(const ClassSDict &classSDict,bool rootOnly)
6833 {
6834   p->addClassHierarchy(classSDict,rootOnly);
6835 }
6836
6837 void NestingContext::addDerivedClasses(const BaseClassList *bcl,bool hideSuper)
6838 {
6839   p->addDerivedClasses(bcl,hideSuper);
6840 }
6841
6842 //------------------------------------------------------------------------
6843
6844 //%% struct ClassTree: Class nesting relations
6845 //%% {
6846 class ClassTreeContext::Private
6847 {
6848   public:
6849     Private()
6850     {
6851       m_classTree.reset(NestingContext::alloc(0,0));
6852       if (Doxygen::namespaceSDict)
6853       {
6854         m_classTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,TRUE);
6855       }
6856       if (Doxygen::classSDict)
6857       {
6858         m_classTree->addClasses(*Doxygen::classSDict,TRUE);
6859       }
6860       //%% Nesting tree
6861       static bool init=FALSE;
6862       if (!init)
6863       {
6864         s_inst.addProperty("tree",          &Private::tree);
6865         s_inst.addProperty("fileName",      &Private::fileName);
6866         s_inst.addProperty("relPath",       &Private::relPath);
6867         s_inst.addProperty("highlight",     &Private::highlight);
6868         s_inst.addProperty("subhighlight",  &Private::subhighlight);
6869         s_inst.addProperty("title",         &Private::title);
6870         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
6871         s_inst.addProperty("maxDepth",      &Private::maxDepth);
6872         init=TRUE;
6873       }
6874     }
6875     TemplateVariant get(const char *n) const
6876     {
6877       return s_inst.get(this,n);
6878     }
6879     TemplateVariant tree() const
6880     {
6881       return m_classTree.get();
6882     }
6883     TemplateVariant fileName() const
6884     {
6885       return "annotated";
6886     }
6887     TemplateVariant relPath() const
6888     {
6889       return "";
6890     }
6891     TemplateVariant highlight() const
6892     {
6893       return "classes";
6894     }
6895     TemplateVariant subhighlight() const
6896     {
6897       return "classlist";
6898     }
6899     TemplateVariant title() const
6900     {
6901       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
6902       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
6903       if (fortranOpt)
6904       {
6905         return theTranslator->trCompoundListFortran();
6906       }
6907       else if (vhdlOpt)
6908       {
6909         return theTranslator->trDesignUnitList();
6910       }
6911       else
6912       {
6913         return theTranslator->trClasses();
6914       }
6915     }
6916     TemplateVariant maxDepth() const
6917     {
6918       if (!m_cache.maxDepthComputed)
6919       {
6920         m_cache.maxDepth = computeMaxDepth(m_classTree.get());
6921         m_cache.maxDepthComputed=TRUE;
6922       }
6923       return m_cache.maxDepth;
6924     }
6925     TemplateVariant preferredDepth() const
6926     {
6927       if (!m_cache.preferredDepthComputed)
6928       {
6929         m_cache.preferredDepth = computePreferredDepth(m_classTree.get(),maxDepth().toInt());
6930         m_cache.preferredDepthComputed=TRUE;
6931       }
6932       return m_cache.preferredDepth;
6933     }
6934   private:
6935     SharedPtr<NestingContext> m_classTree;
6936     struct Cachable
6937     {
6938       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
6939                    preferredDepth(0), preferredDepthComputed(FALSE) {}
6940       int   maxDepth;
6941       bool  maxDepthComputed;
6942       int   preferredDepth;
6943       bool  preferredDepthComputed;
6944     };
6945     mutable Cachable m_cache;
6946     static PropertyMapper<ClassTreeContext::Private> s_inst;
6947 };
6948 //%% }
6949
6950 PropertyMapper<ClassTreeContext::Private> ClassTreeContext::Private::s_inst;
6951
6952 ClassTreeContext::ClassTreeContext() : RefCountedContext("ClassTreeContext")
6953 {
6954   p = new Private;
6955 }
6956
6957 ClassTreeContext::~ClassTreeContext()
6958 {
6959   delete p;
6960 }
6961
6962 TemplateVariant ClassTreeContext::get(const char *name) const
6963 {
6964   return p->get(name);
6965 }
6966
6967 //------------------------------------------------------------------------
6968
6969 //%% list NamespaceList[Namespace] : list of namespaces
6970 class NamespaceListContext::Private : public GenericNodeListContext
6971 {
6972   public:
6973     void addNamespaces(const NamespaceSDict &nsDict)
6974     {
6975       NamespaceSDict::Iterator nli(nsDict);
6976       NamespaceDef *nd;
6977       for (nli.toFirst();(nd=nli.current());++nli)
6978       {
6979         if (nd->isLinkableInProject())
6980         {
6981           append(NamespaceContext::alloc(nd));
6982         }
6983       }
6984     }
6985 };
6986
6987 NamespaceListContext::NamespaceListContext() : RefCountedContext("NamespaceListContext")
6988 {
6989   p = new Private;
6990   p->addNamespaces(*Doxygen::namespaceSDict);
6991 }
6992
6993 NamespaceListContext::~NamespaceListContext()
6994 {
6995   delete p;
6996 }
6997
6998 // TemplateListIntf
6999 int NamespaceListContext::count() const
7000 {
7001   return p->count();
7002 }
7003
7004 TemplateVariant NamespaceListContext::at(int index) const
7005 {
7006   return p->at(index);
7007 }
7008
7009 TemplateListIntf::ConstIterator *NamespaceListContext::createIterator() const
7010 {
7011   return p->createIterator();
7012 }
7013
7014 //------------------------------------------------------------------------
7015
7016 //%% struct NamespaceTree: tree of nested namespace
7017 //%% {
7018 class NamespaceTreeContext::Private
7019 {
7020   public:
7021     Private()
7022     {
7023       m_namespaceTree.reset(NestingContext::alloc(0,0));
7024       if (Doxygen::namespaceSDict)
7025       {
7026         m_namespaceTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,FALSE);
7027       }
7028       //%% Nesting tree
7029       static bool init=FALSE;
7030       if (!init)
7031       {
7032         s_inst.addProperty("tree",          &Private::tree);
7033         s_inst.addProperty("fileName",      &Private::fileName);
7034         s_inst.addProperty("relPath",       &Private::relPath);
7035         s_inst.addProperty("highlight",     &Private::highlight);
7036         s_inst.addProperty("subhighlight",  &Private::subhighlight);
7037         s_inst.addProperty("title",         &Private::title);
7038         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
7039         s_inst.addProperty("maxDepth",      &Private::maxDepth);
7040         init=TRUE;
7041       }
7042     }
7043     TemplateVariant get(const char *n) const
7044     {
7045       return s_inst.get(this,n);
7046     }
7047     TemplateVariant tree() const
7048     {
7049       return m_namespaceTree.get();
7050     }
7051     TemplateVariant fileName() const
7052     {
7053       return "namespaces";
7054     }
7055     TemplateVariant relPath() const
7056     {
7057       return "";
7058     }
7059     TemplateVariant highlight() const
7060     {
7061       return "namespaces";
7062     }
7063     TemplateVariant subhighlight() const
7064     {
7065       return "namespacelist";
7066     }
7067     TemplateVariant title() const
7068     {
7069       static bool javaOpt    = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
7070       static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
7071       static bool vhdlOpt    = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
7072       static bool sliceOpt   = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
7073       if (javaOpt || vhdlOpt)
7074       {
7075         return theTranslator->trPackages();
7076       }
7077       else if (fortranOpt || sliceOpt)
7078       {
7079         return theTranslator->trModulesList();
7080       }
7081       else
7082       {
7083         return theTranslator->trNamespaceList();
7084       }
7085     }
7086     TemplateVariant maxDepth() const
7087     {
7088       if (!m_cache.maxDepthComputed)
7089       {
7090         m_cache.maxDepth = computeMaxDepth(m_namespaceTree.get());
7091         m_cache.maxDepthComputed=TRUE;
7092       }
7093       return m_cache.maxDepth;
7094     }
7095     TemplateVariant preferredDepth() const
7096     {
7097       if (!m_cache.preferredDepthComputed)
7098       {
7099         m_cache.preferredDepth = computePreferredDepth(m_namespaceTree.get(),maxDepth().toInt());
7100         m_cache.preferredDepthComputed=TRUE;
7101       }
7102       return m_cache.preferredDepth;
7103     }
7104   private:
7105     SharedPtr<NestingContext> m_namespaceTree;
7106     struct Cachable
7107     {
7108       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
7109                    preferredDepth(0), preferredDepthComputed(FALSE) {}
7110       int   maxDepth;
7111       bool  maxDepthComputed;
7112       int   preferredDepth;
7113       bool  preferredDepthComputed;
7114     };
7115     mutable Cachable m_cache;
7116     static PropertyMapper<NamespaceTreeContext::Private> s_inst;
7117 };
7118 //%% }
7119
7120 PropertyMapper<NamespaceTreeContext::Private> NamespaceTreeContext::Private::s_inst;
7121
7122 NamespaceTreeContext::NamespaceTreeContext() : RefCountedContext("NamespaceTreeContext")
7123 {
7124   p = new Private;
7125 }
7126
7127 NamespaceTreeContext::~NamespaceTreeContext()
7128 {
7129   delete p;
7130 }
7131
7132 TemplateVariant NamespaceTreeContext::get(const char *name) const
7133 {
7134   return p->get(name);
7135 }
7136
7137 //------------------------------------------------------------------------
7138
7139 //%% list FileList[File] : list of files
7140 class FileListContext::Private : public GenericNodeListContext
7141 {
7142   public:
7143     void addFiles(const FileNameList &fnList)
7144     {
7145       // TODO: if FULL_PATH_NAMES is enabled, the ordering should be dir+file
7146       FileNameListIterator fnli(fnList);
7147       FileName *fn;
7148       for (fnli.toFirst();(fn=fnli.current());++fnli)
7149       {
7150         FileNameIterator fni(*fn);
7151         FileDef *fd;
7152         for (fni.toFirst();(fd=fni.current());++fni)
7153         {
7154           bool doc = fd->isLinkableInProject();
7155           bool src = fd->generateSourceFile();
7156           bool nameOk = !fd->isDocumentationFile();
7157           if (nameOk && (doc || src) && !fd->isReference())
7158           {
7159             append(FileContext::alloc(fd));
7160           }
7161         }
7162       }
7163     }
7164 };
7165
7166 FileListContext::FileListContext() : RefCountedContext("FileListContext")
7167 {
7168   p = new Private;
7169   if (Doxygen::inputNameList) p->addFiles(*Doxygen::inputNameList);
7170 }
7171
7172 FileListContext::~FileListContext()
7173 {
7174   delete p;
7175 }
7176
7177 // TemplateListIntf
7178 int FileListContext::count() const
7179 {
7180   return p->count();
7181 }
7182
7183 TemplateVariant FileListContext::at(int index) const
7184 {
7185   return p->at(index);
7186 }
7187
7188 TemplateListIntf::ConstIterator *FileListContext::createIterator() const
7189 {
7190   return p->createIterator();
7191 }
7192
7193 //------------------------------------------------------------------------
7194
7195 //%% list DirList[Dir] : list of files
7196 class DirListContext::Private : public GenericNodeListContext
7197 {
7198   public:
7199     Private()
7200     {
7201       DirDef *dir;
7202       DirSDict::Iterator sdi(*Doxygen::directories);
7203       for (sdi.toFirst();(dir=sdi.current());++sdi)
7204       {
7205         append(DirContext::alloc(dir));
7206       }
7207     }
7208 };
7209
7210 DirListContext::DirListContext() : RefCountedContext("DirListContext")
7211 {
7212   p = new Private;
7213 }
7214
7215 DirListContext::~DirListContext()
7216 {
7217   delete p;
7218 }
7219
7220 // TemplateListIntf
7221 int DirListContext::count() const
7222 {
7223   return p->count();
7224 }
7225
7226 TemplateVariant DirListContext::at(int index) const
7227 {
7228   return p->at(index);
7229 }
7230
7231 TemplateListIntf::ConstIterator *DirListContext::createIterator() const
7232 {
7233   return p->createIterator();
7234 }
7235
7236
7237 //------------------------------------------------------------------------
7238
7239 //%% list UsedFiles[File] : list of files
7240 class UsedFilesContext::Private : public GenericNodeListContext
7241 {
7242   public:
7243     void addFile(FileDef *fd)
7244     {
7245       append(FileContext::alloc(fd));
7246     }
7247 };
7248
7249 UsedFilesContext::UsedFilesContext(ClassDef *cd) : RefCountedContext("UsedFilesContext")
7250 {
7251   p = new Private;
7252   if (cd)
7253   {
7254     QListIterator<FileDef> li(cd->usedFiles());
7255     FileDef *fd;
7256     for (li.toFirst();(fd=li.current());++li)
7257     {
7258       p->addFile(fd);
7259     }
7260   }
7261 }
7262
7263 UsedFilesContext::~UsedFilesContext()
7264 {
7265   delete p;
7266 }
7267
7268 // TemplateListIntf
7269 int UsedFilesContext::count() const
7270 {
7271   return p->count();
7272 }
7273
7274 TemplateVariant UsedFilesContext::at(int index) const
7275 {
7276   return p->at(index);
7277 }
7278
7279 TemplateListIntf::ConstIterator *UsedFilesContext::createIterator() const
7280 {
7281   return p->createIterator();
7282 }
7283
7284 void UsedFilesContext::addFile(FileDef *fd)
7285 {
7286   p->addFile(fd);
7287 }
7288
7289 //------------------------------------------------------------------------
7290
7291 //%% struct FileTree: tree of directories and files
7292 //%% {
7293 class FileTreeContext::Private
7294 {
7295   public:
7296     Private()
7297     {
7298       // Add dirs tree
7299       m_dirFileTree.reset(NestingContext::alloc(0,0));
7300       if (Doxygen::directories)
7301       {
7302         m_dirFileTree->addDirs(*Doxygen::directories);
7303       }
7304       if (Doxygen::inputNameList)
7305       {
7306         m_dirFileTree->addFiles(*Doxygen::inputNameList);
7307       }
7308       //%% DirFile tree:
7309       static bool init=FALSE;
7310       if (!init)
7311       {
7312         s_inst.addProperty("tree",          &Private::tree);
7313         s_inst.addProperty("fileName",      &Private::fileName);
7314         s_inst.addProperty("relPath",       &Private::relPath);
7315         s_inst.addProperty("highlight",     &Private::highlight);
7316         s_inst.addProperty("subhighlight",  &Private::subhighlight);
7317         s_inst.addProperty("title",         &Private::title);
7318         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
7319         s_inst.addProperty("maxDepth",      &Private::maxDepth);
7320         init=TRUE;
7321       }
7322     }
7323     TemplateVariant get(const char *n) const
7324     {
7325       return s_inst.get(this,n);
7326     }
7327     TemplateVariant tree() const
7328     {
7329       return m_dirFileTree.get();
7330     }
7331     TemplateVariant fileName() const
7332     {
7333       return "files";
7334     }
7335     TemplateVariant relPath() const
7336     {
7337       return "";
7338     }
7339     TemplateVariant highlight() const
7340     {
7341       return "files";
7342     }
7343     TemplateVariant subhighlight() const
7344     {
7345       return "filelist";
7346     }
7347     TemplateVariant title() const
7348     {
7349       return theTranslator->trFileList();
7350     }
7351     TemplateVariant maxDepth() const
7352     {
7353       if (!m_cache.maxDepthComputed)
7354       {
7355         m_cache.maxDepth = computeMaxDepth(m_dirFileTree.get());
7356         m_cache.maxDepthComputed=TRUE;
7357       }
7358       return m_cache.maxDepth;
7359     }
7360     TemplateVariant preferredDepth() const
7361     {
7362       if (!m_cache.preferredDepthComputed)
7363       {
7364         m_cache.preferredDepth = computePreferredDepth(m_dirFileTree.get(),maxDepth().toInt());
7365         m_cache.preferredDepthComputed=TRUE;
7366       }
7367       return m_cache.preferredDepth;
7368     }
7369   private:
7370     SharedPtr<NestingContext> m_dirFileTree;
7371     struct Cachable
7372     {
7373       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
7374                    preferredDepth(0), preferredDepthComputed(FALSE) {}
7375       int   maxDepth;
7376       bool  maxDepthComputed;
7377       int   preferredDepth;
7378       bool  preferredDepthComputed;
7379     };
7380     mutable Cachable m_cache;
7381     static PropertyMapper<FileTreeContext::Private> s_inst;
7382 };
7383 //%% }
7384
7385 PropertyMapper<FileTreeContext::Private> FileTreeContext::Private::s_inst;
7386
7387 FileTreeContext::FileTreeContext() : RefCountedContext("FileTreeContext")
7388 {
7389   p = new Private;
7390 }
7391
7392 FileTreeContext::~FileTreeContext()
7393 {
7394   delete p;
7395 }
7396
7397 TemplateVariant FileTreeContext::get(const char *name) const
7398 {
7399   return p->get(name);
7400 }
7401
7402 //------------------------------------------------------------------------
7403
7404 //%% struct PageTree: tree of related pages
7405 //%% {
7406 class PageTreeContext::Private
7407 {
7408   public:
7409     Private(const PageSDict *pages)
7410     {
7411       m_pageTree.reset(NestingContext::alloc(0,0));
7412       // Add pages
7413       if (pages)
7414       {
7415         m_pageTree->addPages(*pages,TRUE);
7416       }
7417
7418       //%% PageNodeList tree:
7419       static bool init=FALSE;
7420       if (!init)
7421       {
7422         s_inst.addProperty("tree",          &Private::tree);
7423         s_inst.addProperty("fileName",      &Private::fileName);
7424         s_inst.addProperty("relPath",       &Private::relPath);
7425         s_inst.addProperty("highlight",     &Private::highlight);
7426         s_inst.addProperty("subhighlight",  &Private::subhighlight);
7427         s_inst.addProperty("title",         &Private::title);
7428         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
7429         s_inst.addProperty("maxDepth",      &Private::maxDepth);
7430         init=TRUE;
7431       }
7432     }
7433     TemplateVariant get(const char *n) const
7434     {
7435       return s_inst.get(this,n);
7436     }
7437     TemplateVariant tree() const
7438     {
7439       return m_pageTree.get();
7440     }
7441     TemplateVariant fileName() const
7442     {
7443       return "pages";
7444     }
7445     TemplateVariant relPath() const
7446     {
7447       return "";
7448     }
7449     TemplateVariant highlight() const
7450     {
7451       return "pages";
7452     }
7453     TemplateVariant subhighlight() const
7454     {
7455       return "";
7456     }
7457     TemplateVariant title() const
7458     {
7459       return theTranslator->trRelatedPages();
7460     }
7461     TemplateVariant maxDepth() const
7462     {
7463       if (!m_cache.maxDepthComputed)
7464       {
7465         m_cache.maxDepth = computeMaxDepth(m_pageTree.get());
7466         m_cache.maxDepthComputed=TRUE;
7467       }
7468       return m_cache.maxDepth;
7469     }
7470     TemplateVariant preferredDepth() const
7471     {
7472       if (!m_cache.preferredDepthComputed)
7473       {
7474         m_cache.preferredDepth = computePreferredDepth(m_pageTree.get(),maxDepth().toInt());
7475         m_cache.preferredDepthComputed=TRUE;
7476       }
7477       return m_cache.preferredDepth;
7478     }
7479   private:
7480     SharedPtr<NestingContext> m_pageTree;
7481     struct Cachable
7482     {
7483       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
7484                    preferredDepth(0), preferredDepthComputed(FALSE) {}
7485       int   maxDepth;
7486       bool  maxDepthComputed;
7487       int   preferredDepth;
7488       bool  preferredDepthComputed;
7489     };
7490     mutable Cachable m_cache;
7491     static PropertyMapper<PageTreeContext::Private> s_inst;
7492 };
7493 //%% }
7494
7495 PropertyMapper<PageTreeContext::Private> PageTreeContext::Private::s_inst;
7496
7497 PageTreeContext::PageTreeContext(const PageSDict *pages) : RefCountedContext("PageTreeContext")
7498 {
7499   p = new Private(pages);
7500 }
7501
7502 PageTreeContext::~PageTreeContext()
7503 {
7504   delete p;
7505 }
7506
7507 TemplateVariant PageTreeContext::get(const char *name) const
7508 {
7509   return p->get(name);
7510 }
7511
7512 //------------------------------------------------------------------------
7513
7514 //%% list PageList[Page]: list of pages
7515 class PageListContext::Private : public GenericNodeListContext
7516 {
7517   public:
7518     void addPages(const PageSDict &pages)
7519     {
7520       PageSDict::Iterator pdi(pages);
7521       PageDef *pd=0;
7522       for (pdi.toFirst();(pd=pdi.current());++pdi)
7523       {
7524         if (!pd->getGroupDef() && !pd->isReference())
7525         {
7526           append(PageContext::alloc(pd,FALSE,FALSE));
7527         }
7528       }
7529     }
7530 };
7531
7532 PageListContext::PageListContext(const PageSDict *pages) : RefCountedContext("PageListContext")
7533 {
7534   p = new Private;
7535   if (pages) p->addPages(*pages);
7536 }
7537
7538 PageListContext::~PageListContext()
7539 {
7540   delete p;
7541 }
7542
7543 // TemplateListIntf
7544 int PageListContext::count() const
7545 {
7546   return p->count();
7547 }
7548
7549 TemplateVariant PageListContext::at(int index) const
7550 {
7551   return p->at(index);
7552 }
7553
7554 TemplateListIntf::ConstIterator *PageListContext::createIterator() const
7555 {
7556   return p->createIterator();
7557 }
7558
7559 //------------------------------------------------------------------------
7560
7561 //%% list ExampleList[Page]: list of pages
7562 class ExampleListContext::Private : public GenericNodeListContext
7563 {
7564   public:
7565     Private()
7566     {
7567       if (Doxygen::exampleSDict)
7568       {
7569         PageSDict::Iterator pdi(*Doxygen::exampleSDict);
7570         PageDef *pd=0;
7571         for (pdi.toFirst();(pd=pdi.current());++pdi)
7572         {
7573           if (!pd->getGroupDef() && !pd->isReference())
7574           {
7575             append(PageContext::alloc(pd,FALSE,TRUE));
7576           }
7577         }
7578       }
7579     }
7580 };
7581
7582 ExampleListContext::ExampleListContext() : RefCountedContext("ExampleListContext")
7583 {
7584   p = new Private;
7585 }
7586
7587 ExampleListContext::~ExampleListContext()
7588 {
7589   delete p;
7590 }
7591
7592 // TemplateListIntf
7593 int ExampleListContext::count() const
7594 {
7595   return p->count();
7596 }
7597
7598 TemplateVariant ExampleListContext::at(int index) const
7599 {
7600   return p->at(index);
7601 }
7602
7603 TemplateListIntf::ConstIterator *ExampleListContext::createIterator() const
7604 {
7605   return p->createIterator();
7606 }
7607
7608 //------------------------------------------------------------------------
7609
7610 //%% list ModuleList[ModuleNode]: list of directories and/or files
7611 class ModuleListContext::Private : public GenericNodeListContext
7612 {
7613   public:
7614     void addModules()
7615     {
7616       GroupSDict::Iterator gli(*Doxygen::groupSDict);
7617       GroupDef *gd;
7618       for (gli.toFirst();(gd=gli.current());++gli)
7619       {
7620         if (!gd->isReference())
7621         {
7622           append(ModuleContext::alloc(gd));
7623         }
7624       }
7625     }
7626 };
7627
7628 ModuleListContext::ModuleListContext() : RefCountedContext("ModuleListContext")
7629 {
7630   p = new Private;
7631   p->addModules();
7632 }
7633
7634 ModuleListContext::~ModuleListContext()
7635 {
7636   delete p;
7637 }
7638
7639 // TemplateListIntf
7640 int ModuleListContext::count() const
7641 {
7642   return p->count();
7643 }
7644
7645 TemplateVariant ModuleListContext::at(int index) const
7646 {
7647   return p->at(index);
7648 }
7649
7650 TemplateListIntf::ConstIterator *ModuleListContext::createIterator() const
7651 {
7652   return p->createIterator();
7653 }
7654
7655 //------------------------------------------------------------------------
7656
7657 //%% struct ModuleTree: tree of modules
7658 //%% {
7659 class ModuleTreeContext::Private
7660 {
7661   public:
7662     Private()
7663     {
7664       m_moduleTree.reset(NestingContext::alloc(0,0));
7665       // Add modules
7666       if (Doxygen::groupSDict)
7667       {
7668         m_moduleTree->addModules(*Doxygen::groupSDict);
7669       }
7670
7671       //%% ModuleList tree:
7672       static bool init=FALSE;
7673       if (!init)
7674       {
7675         s_inst.addProperty("tree",          &Private::tree);
7676         s_inst.addProperty("fileName",      &Private::fileName);
7677         s_inst.addProperty("relPath",       &Private::relPath);
7678         s_inst.addProperty("highlight",     &Private::highlight);
7679         s_inst.addProperty("subhighlight",  &Private::subhighlight);
7680         s_inst.addProperty("title",         &Private::title);
7681         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
7682         s_inst.addProperty("maxDepth",      &Private::maxDepth);
7683         init=TRUE;
7684       }
7685     }
7686     TemplateVariant get(const char *n) const
7687     {
7688       return s_inst.get(this,n);
7689     }
7690     TemplateVariant tree() const
7691     {
7692       return m_moduleTree.get();
7693     }
7694     TemplateVariant fileName() const
7695     {
7696       return "modules";
7697     }
7698     TemplateVariant relPath() const
7699     {
7700       return "";
7701     }
7702     TemplateVariant highlight() const
7703     {
7704       return "modules";
7705     }
7706     TemplateVariant subhighlight() const
7707     {
7708       return "";
7709     }
7710     TemplateVariant title() const
7711     {
7712       return theTranslator->trModules();
7713     }
7714     TemplateVariant maxDepth() const
7715     {
7716       if (!m_cache.maxDepthComputed)
7717       {
7718         m_cache.maxDepth = computeMaxDepth(m_moduleTree.get());
7719         m_cache.maxDepthComputed=TRUE;
7720       }
7721       return m_cache.maxDepth;
7722     }
7723     TemplateVariant preferredDepth() const
7724     {
7725       if (!m_cache.preferredDepthComputed)
7726       {
7727         m_cache.preferredDepth = computePreferredDepth(m_moduleTree.get(),maxDepth().toInt());
7728         m_cache.preferredDepthComputed=TRUE;
7729       }
7730       return m_cache.preferredDepth;
7731     }
7732   private:
7733     SharedPtr<NestingContext> m_moduleTree;
7734     struct Cachable
7735     {
7736       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
7737                    preferredDepth(0), preferredDepthComputed(FALSE) {}
7738       int   maxDepth;
7739       bool  maxDepthComputed;
7740       int   preferredDepth;
7741       bool  preferredDepthComputed;
7742     };
7743     mutable Cachable m_cache;
7744     static PropertyMapper<ModuleTreeContext::Private> s_inst;
7745 };
7746 //%% }
7747
7748 PropertyMapper<ModuleTreeContext::Private> ModuleTreeContext::Private::s_inst;
7749
7750 ModuleTreeContext::ModuleTreeContext() : RefCountedContext("ModuleTreeContext")
7751 {
7752   p = new Private;
7753 }
7754
7755 ModuleTreeContext::~ModuleTreeContext()
7756 {
7757   delete p;
7758 }
7759
7760 TemplateVariant ModuleTreeContext::get(const char *name) const
7761 {
7762   return p->get(name);
7763 }
7764
7765 //------------------------------------------------------------------------
7766
7767 //%% struct NavPathElem: list of examples page
7768 //%% {
7769 class NavPathElemContext::Private
7770 {
7771   public:
7772     Private(Definition *def) : m_def(def)
7773     {
7774       static bool init=FALSE;
7775       if (!init)
7776       {
7777         s_inst.addProperty("isLinkable",       &Private::isLinkable);
7778         s_inst.addProperty("fileName",         &Private::fileName);
7779         s_inst.addProperty("anchor",           &Private::anchor);
7780         s_inst.addProperty("text",             &Private::text);
7781         s_inst.addProperty("isReference",      &Private::isReference);
7782         s_inst.addProperty("externalReference",&Private::externalReference);
7783         init=TRUE;
7784       }
7785     }
7786     TemplateVariant get(const char *n) const
7787     {
7788       return s_inst.get(this,n);
7789     }
7790     TemplateVariant isLinkable() const
7791     {
7792       return m_def->isLinkable();
7793     }
7794     TemplateVariant anchor() const
7795     {
7796       return m_def->anchor();
7797     }
7798     TemplateVariant fileName() const
7799     {
7800       return m_def->getOutputFileBase();
7801     }
7802     TemplateVariant text() const
7803     {
7804       Definition::DefType type = m_def->definitionType();
7805       QCString text = m_def->localName();
7806       if (type==Definition::TypeGroup)
7807       {
7808         text = ((const GroupDef*)m_def)->groupTitle();
7809       }
7810       else if (type==Definition::TypePage && !(((const PageDef*)m_def)->title().isEmpty()))
7811       {
7812         text = ((const PageDef*)m_def)->title();
7813       }
7814       else if (type==Definition::TypeClass)
7815       {
7816         if (text.right(2)=="-p")
7817         {
7818           text = text.left(text.length()-2);
7819         }
7820       }
7821       return text;
7822     }
7823     TemplateVariant isReference() const
7824     {
7825       return m_def->isReference();
7826     }
7827     QCString relPathAsString() const
7828     {
7829       static bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
7830       return createSubdirs ? QCString("../../") : QCString("");
7831     }
7832     TemplateVariant externalReference() const
7833     {
7834       return m_def->externalReference(relPathAsString());
7835     }
7836   private:
7837     Definition *m_def;
7838     static PropertyMapper<NavPathElemContext::Private> s_inst;
7839 };
7840 //%% }
7841
7842 PropertyMapper<NavPathElemContext::Private> NavPathElemContext::Private::s_inst;
7843
7844 NavPathElemContext::NavPathElemContext(Definition *def) : RefCountedContext("NavPathElemContext")
7845 {
7846   p = new Private(def);
7847 }
7848
7849 NavPathElemContext::~NavPathElemContext()
7850 {
7851   delete p;
7852 }
7853
7854 TemplateVariant NavPathElemContext::get(const char *name) const
7855 {
7856   return p->get(name);
7857 }
7858
7859
7860 //------------------------------------------------------------------------
7861
7862 //%% struct ExampleList: list of examples page
7863 //%% {
7864 class ExampleTreeContext::Private
7865 {
7866   public:
7867     Private()
7868     {
7869       m_exampleTree.reset(NestingContext::alloc(0,0));
7870       // Add pages
7871       if (Doxygen::exampleSDict)
7872       {
7873         m_exampleTree->addPages(*Doxygen::exampleSDict,TRUE);
7874       }
7875
7876       static bool init=FALSE;
7877       if (!init)
7878       {
7879         s_inst.addProperty("tree",          &Private::tree);
7880         s_inst.addProperty("fileName",      &Private::fileName);
7881         s_inst.addProperty("relPath",       &Private::relPath);
7882         s_inst.addProperty("highlight",     &Private::highlight);
7883         s_inst.addProperty("subhighlight",  &Private::subhighlight);
7884         s_inst.addProperty("title",         &Private::title);
7885         s_inst.addProperty("preferredDepth",&Private::preferredDepth);
7886         s_inst.addProperty("maxDepth",      &Private::maxDepth);
7887         init=TRUE;
7888       }
7889     }
7890     TemplateVariant get(const char *n) const
7891     {
7892       return s_inst.get(this,n);
7893     }
7894     TemplateVariant tree() const
7895     {
7896       return m_exampleTree.get();
7897     }
7898     TemplateVariant fileName() const
7899     {
7900       return "examples";
7901     }
7902     TemplateVariant relPath() const
7903     {
7904       return "";
7905     }
7906     TemplateVariant highlight() const
7907     {
7908       return "examples";
7909     }
7910     TemplateVariant subhighlight() const
7911     {
7912       return "";
7913     }
7914     TemplateVariant title() const
7915     {
7916       return theTranslator->trExamples();
7917     }
7918     TemplateVariant maxDepth() const
7919     {
7920       if (!m_cache.maxDepthComputed)
7921       {
7922         m_cache.maxDepth = computeMaxDepth(m_exampleTree.get());
7923         m_cache.maxDepthComputed=TRUE;
7924       }
7925       return m_cache.maxDepth;
7926     }
7927     TemplateVariant preferredDepth() const
7928     {
7929       if (!m_cache.preferredDepthComputed)
7930       {
7931         m_cache.preferredDepth = computePreferredDepth(m_exampleTree.get(),maxDepth().toInt());
7932         m_cache.preferredDepthComputed=TRUE;
7933       }
7934       return m_cache.preferredDepth;
7935     }
7936   private:
7937     SharedPtr<NestingContext> m_exampleTree;
7938     struct Cachable
7939     {
7940       Cachable() : maxDepth(0), maxDepthComputed(FALSE),
7941                    preferredDepth(0), preferredDepthComputed(FALSE) {}
7942       int   maxDepth;
7943       bool  maxDepthComputed;
7944       int   preferredDepth;
7945       bool  preferredDepthComputed;
7946     };
7947     mutable Cachable m_cache;
7948     static PropertyMapper<ExampleTreeContext::Private> s_inst;
7949 };
7950 //%% }
7951
7952 PropertyMapper<ExampleTreeContext::Private> ExampleTreeContext::Private::s_inst;
7953
7954 ExampleTreeContext::ExampleTreeContext() : RefCountedContext("ExampleTreeContext")
7955 {
7956   p = new Private;
7957 }
7958
7959 ExampleTreeContext::~ExampleTreeContext()
7960 {
7961   delete p;
7962 }
7963
7964 TemplateVariant ExampleTreeContext::get(const char *name) const
7965 {
7966   return p->get(name);
7967 }
7968
7969 //------------------------------------------------------------------------
7970
7971 //%% struct GlobalsIndex: list of examples page
7972 //%% {
7973 class GlobalsIndexContext::Private
7974 {
7975   public:
7976     Private()
7977     {
7978       static bool init=FALSE;
7979       if (!init)
7980       {
7981         s_inst.addProperty("all",         &Private::all);
7982         s_inst.addProperty("functions",   &Private::functions);
7983         s_inst.addProperty("variables",   &Private::variables);
7984         s_inst.addProperty("typedefs",    &Private::typedefs);
7985         s_inst.addProperty("enums",       &Private::enums);
7986         s_inst.addProperty("enumValues",  &Private::enumValues);
7987         s_inst.addProperty("macros",      &Private::macros);
7988         s_inst.addProperty("properties",  &Private::properties);
7989         s_inst.addProperty("events",      &Private::events);
7990         s_inst.addProperty("related",     &Private::related);
7991         s_inst.addProperty("fileName",    &Private::fileName);
7992         s_inst.addProperty("relPath",     &Private::relPath);
7993         s_inst.addProperty("highlight",   &Private::highlight);
7994         s_inst.addProperty("subhighlight",&Private::subhighlight);
7995         s_inst.addProperty("title",       &Private::title);
7996         init=TRUE;
7997       }
7998     }
7999     TemplateVariant get(const char *n) const
8000     {
8001       return s_inst.get(this,n);
8002     }
8003     typedef bool (MemberDef::*MemberFunc)() const;
8004     TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
8005     {
8006       if (!listRef)
8007       {
8008         TemplateList *list = TemplateList::alloc();
8009         MemberName *mn;
8010         MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
8011         for (fnli.toFirst();(mn=fnli.current());++fnli)
8012         {
8013           MemberDef *md;
8014           MemberNameIterator mni(*mn);
8015           for (mni.toFirst();(md=mni.current());++mni)
8016           {
8017             FileDef *fd=md->getFileDef();
8018             if (fd && fd->isLinkableInProject() &&
8019                 !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject())
8020             {
8021               if (filter==0 || (md->*filter)())
8022               {
8023                 list->append(MemberContext::alloc(md));
8024               }
8025             }
8026           }
8027         }
8028         listRef.reset(list);
8029       }
8030       return listRef.get();
8031     }
8032     TemplateVariant all() const
8033     {
8034       return getMembersFiltered(m_cache.all,0);
8035     }
8036     TemplateVariant functions() const
8037     {
8038       return getMembersFiltered(m_cache.functions,&MemberDef::isFunction);
8039     }
8040     TemplateVariant variables() const
8041     {
8042       return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
8043     }
8044     TemplateVariant typedefs() const
8045     {
8046       return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
8047     }
8048     TemplateVariant enums() const
8049     {
8050       return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
8051     }
8052     TemplateVariant enumValues() const
8053     {
8054       return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
8055     }
8056     TemplateVariant macros() const
8057     {
8058       return getMembersFiltered(m_cache.macros,&MemberDef::isDefine);
8059     }
8060     TemplateVariant properties() const
8061     {
8062       return FALSE;
8063     }
8064     TemplateVariant events() const
8065     {
8066       return FALSE;
8067     }
8068     TemplateVariant related() const
8069     {
8070       return FALSE;
8071     }
8072     TemplateVariant fileName() const
8073     {
8074       return "globals";
8075     }
8076     TemplateVariant relPath() const
8077     {
8078       return "";
8079     }
8080     TemplateVariant highlight() const
8081     {
8082       return "files";
8083     }
8084     TemplateVariant subhighlight() const
8085     {
8086       return "filemembers";
8087     }
8088     TemplateVariant title() const
8089     {
8090       return theTranslator->trFileMembers();
8091     }
8092   private:
8093     struct Cachable
8094     {
8095       Cachable() {}
8096       SharedPtr<TemplateList> all;
8097       SharedPtr<TemplateList> functions;
8098       SharedPtr<TemplateList> variables;
8099       SharedPtr<TemplateList> typedefs;
8100       SharedPtr<TemplateList> enums;
8101       SharedPtr<TemplateList> enumValues;
8102       SharedPtr<TemplateList> macros;
8103     };
8104     mutable Cachable m_cache;
8105     static PropertyMapper<GlobalsIndexContext::Private> s_inst;
8106 };
8107 //%% }
8108
8109 PropertyMapper<GlobalsIndexContext::Private> GlobalsIndexContext::Private::s_inst;
8110
8111 GlobalsIndexContext::GlobalsIndexContext() : RefCountedContext("GlobalsIndexContext")
8112 {
8113   p = new Private;
8114 }
8115
8116 GlobalsIndexContext::~GlobalsIndexContext()
8117 {
8118   delete p;
8119 }
8120
8121 TemplateVariant GlobalsIndexContext::get(const char *name) const
8122 {
8123   return p->get(name);
8124 }
8125
8126 //------------------------------------------------------------------------
8127
8128 //%% struct ClassMembersIndex: list of examples page
8129 //%% {
8130 class ClassMembersIndexContext::Private
8131 {
8132   public:
8133     Private()
8134     {
8135       static bool init=FALSE;
8136       if (!init)
8137       {
8138         s_inst.addProperty("all",         &Private::all);
8139         s_inst.addProperty("functions",   &Private::functions);
8140         s_inst.addProperty("variables",   &Private::variables);
8141         s_inst.addProperty("typedefs",    &Private::typedefs);
8142         s_inst.addProperty("enums",       &Private::enums);
8143         s_inst.addProperty("enumValues",  &Private::enumValues);
8144         s_inst.addProperty("macros",      &Private::macros);
8145         s_inst.addProperty("properties",  &Private::properties);
8146         s_inst.addProperty("events",      &Private::events);
8147         s_inst.addProperty("related",     &Private::related);
8148         s_inst.addProperty("fileName",    &Private::fileName);
8149         s_inst.addProperty("relPath",     &Private::relPath);
8150         s_inst.addProperty("highlight",   &Private::highlight);
8151         s_inst.addProperty("subhighlight",&Private::subhighlight);
8152         s_inst.addProperty("title",       &Private::title);
8153         init=TRUE;
8154       }
8155     }
8156     TemplateVariant get(const char *n) const
8157     {
8158       return s_inst.get(this,n);
8159     }
8160     typedef bool (MemberDef::*MemberFunc)() const;
8161     TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
8162     {
8163       if (!listRef)
8164       {
8165         TemplateList *list = TemplateList::alloc();
8166         MemberName *mn;
8167         MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
8168         for (mnli.toFirst();(mn=mnli.current());++mnli)
8169         {
8170           MemberDef *md;
8171           MemberNameIterator mni(*mn);
8172           for (mni.toFirst();(md=mni.current());++mni)
8173           {
8174             ClassDef *cd = md->getClassDef();
8175             if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 &&
8176                 md->isLinkableInProject() && !md->name().isEmpty())
8177             {
8178               if (filter==0 || (md->*filter)())
8179               {
8180                 list->append(MemberContext::alloc(md));
8181               }
8182             }
8183           }
8184         }
8185         listRef.reset(list);
8186       }
8187       return listRef.get();
8188     }
8189     TemplateVariant all() const
8190     {
8191       return getMembersFiltered(m_cache.all,&MemberDef::isNotFriend);
8192     }
8193     TemplateVariant functions() const
8194     {
8195       return getMembersFiltered(m_cache.functions,&MemberDef::isFunctionOrSignalSlot);
8196     }
8197     TemplateVariant variables() const
8198     {
8199       return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
8200     }
8201     TemplateVariant typedefs() const
8202     {
8203       return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
8204     }
8205     TemplateVariant enums() const
8206     {
8207       return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
8208     }
8209     TemplateVariant enumValues() const
8210     {
8211       return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
8212     }
8213     TemplateVariant macros() const
8214     {
8215       return FALSE;
8216     }
8217     TemplateVariant properties() const
8218     {
8219       return getMembersFiltered(m_cache.properties,&MemberDef::isProperty);
8220     }
8221     TemplateVariant events() const
8222     {
8223       return getMembersFiltered(m_cache.events,&MemberDef::isEvent);
8224     }
8225     TemplateVariant related() const
8226     {
8227       return getMembersFiltered(m_cache.related,&MemberDef::isRelated);
8228     }
8229     TemplateVariant fileName() const
8230     {
8231       return "functions";
8232     }
8233     TemplateVariant relPath() const
8234     {
8235       return "";
8236     }
8237     TemplateVariant highlight() const
8238     {
8239       return "classes";
8240     }
8241     TemplateVariant subhighlight() const
8242     {
8243       return "classmembers";
8244     }
8245     TemplateVariant title() const
8246     {
8247       return theTranslator->trCompoundMembers();
8248     }
8249   private:
8250     struct Cachable
8251     {
8252       Cachable() {}
8253       SharedPtr<TemplateList> all;
8254       SharedPtr<TemplateList> functions;
8255       SharedPtr<TemplateList> variables;
8256       SharedPtr<TemplateList> typedefs;
8257       SharedPtr<TemplateList> enums;
8258       SharedPtr<TemplateList> enumValues;
8259       SharedPtr<TemplateList> properties;
8260       SharedPtr<TemplateList> events;
8261       SharedPtr<TemplateList> related;
8262     };
8263     mutable Cachable m_cache;
8264     static PropertyMapper<ClassMembersIndexContext::Private> s_inst;
8265 };
8266 //%% }
8267
8268 PropertyMapper<ClassMembersIndexContext::Private> ClassMembersIndexContext::Private::s_inst;
8269
8270 ClassMembersIndexContext::ClassMembersIndexContext() : RefCountedContext("ClassMembersIndexContext")
8271 {
8272   p = new Private;
8273 }
8274
8275 ClassMembersIndexContext::~ClassMembersIndexContext()
8276 {
8277   delete p;
8278 }
8279
8280 TemplateVariant ClassMembersIndexContext::get(const char *name) const
8281 {
8282   return p->get(name);
8283 }
8284
8285 //------------------------------------------------------------------------
8286
8287 //%% struct NamespaceMembersIndex: list of examples page
8288 //%% {
8289 class NamespaceMembersIndexContext::Private
8290 {
8291   public:
8292     Private()
8293     {
8294       static bool init=FALSE;
8295       if (!init)
8296       {
8297         s_inst.addProperty("all",         &Private::all);
8298         s_inst.addProperty("functions",   &Private::functions);
8299         s_inst.addProperty("variables",   &Private::variables);
8300         s_inst.addProperty("typedefs",    &Private::typedefs);
8301         s_inst.addProperty("enums",       &Private::enums);
8302         s_inst.addProperty("enumValues",  &Private::enumValues);
8303         s_inst.addProperty("macros",      &Private::macros);
8304         s_inst.addProperty("properties",  &Private::properties);
8305         s_inst.addProperty("events",      &Private::events);
8306         s_inst.addProperty("related",     &Private::related);
8307         s_inst.addProperty("fileName",    &Private::fileName);
8308         s_inst.addProperty("relPath",     &Private::relPath);
8309         s_inst.addProperty("highlight",   &Private::highlight);
8310         s_inst.addProperty("subhighlight",&Private::subhighlight);
8311         s_inst.addProperty("title",       &Private::title);
8312         init=TRUE;
8313       }
8314     }
8315     TemplateVariant get(const char *n) const
8316     {
8317       return s_inst.get(this,n);
8318     }
8319     typedef bool (MemberDef::*MemberFunc)() const;
8320     TemplateVariant getMembersFiltered(SharedPtr<TemplateList> &listRef,MemberFunc filter) const
8321     {
8322       if (!listRef)
8323       {
8324         TemplateList *list = TemplateList::alloc();
8325         MemberName *mn;
8326         MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
8327         for (fnli.toFirst();(mn=fnli.current());++fnli)
8328         {
8329           MemberDef *md;
8330           MemberNameIterator mni(*mn);
8331           for (mni.toFirst();(md=mni.current());++mni)
8332           {
8333             NamespaceDef *nd=md->getNamespaceDef();
8334             if (nd && nd->isLinkableInProject() &&
8335                 !md->name().isEmpty() && md->isLinkableInProject())
8336             {
8337               if (filter==0 || (md->*filter)())
8338               {
8339                 list->append(MemberContext::alloc(md));
8340               }
8341             }
8342           }
8343         }
8344         listRef.reset(list);
8345       }
8346       return listRef.get();
8347     }
8348     TemplateVariant all() const
8349     {
8350       return getMembersFiltered(m_cache.all,0);
8351     }
8352     TemplateVariant functions() const
8353     {
8354       return getMembersFiltered(m_cache.functions,&MemberDef::isFunction);
8355     }
8356     TemplateVariant variables() const
8357     {
8358       return getMembersFiltered(m_cache.variables,&MemberDef::isVariable);
8359     }
8360     TemplateVariant typedefs() const
8361     {
8362       return getMembersFiltered(m_cache.typedefs,&MemberDef::isTypedef);
8363     }
8364     TemplateVariant enums() const
8365     {
8366       return getMembersFiltered(m_cache.enums,&MemberDef::isEnumerate);
8367     }
8368     TemplateVariant enumValues() const
8369     {
8370       return getMembersFiltered(m_cache.enumValues,&MemberDef::isEnumValue);
8371     }
8372     TemplateVariant macros() const
8373     {
8374       return FALSE;
8375     }
8376     TemplateVariant properties() const
8377     {
8378       return FALSE;
8379     }
8380     TemplateVariant events() const
8381     {
8382       return FALSE;
8383     }
8384     TemplateVariant related() const
8385     {
8386       return FALSE;
8387     }
8388     TemplateVariant fileName() const
8389     {
8390       return "namespacemembers";
8391     }
8392     TemplateVariant relPath() const
8393     {
8394       return "";
8395     }
8396     TemplateVariant highlight() const
8397     {
8398       return "namespaces";
8399     }
8400     TemplateVariant subhighlight() const
8401     {
8402       return "namespacemembers";
8403     }
8404     TemplateVariant title() const
8405     {
8406       return theTranslator->trNamespaceMembers();
8407     }
8408   private:
8409     struct Cachable
8410     {
8411       Cachable() {}
8412       SharedPtr<TemplateList> all;
8413       SharedPtr<TemplateList> functions;
8414       SharedPtr<TemplateList> variables;
8415       SharedPtr<TemplateList> typedefs;
8416       SharedPtr<TemplateList> enums;
8417       SharedPtr<TemplateList> enumValues;
8418     };
8419     mutable Cachable m_cache;
8420     static PropertyMapper<NamespaceMembersIndexContext::Private> s_inst;
8421 };
8422 //%% }
8423
8424 PropertyMapper<NamespaceMembersIndexContext::Private> NamespaceMembersIndexContext::Private::s_inst;
8425
8426 NamespaceMembersIndexContext::NamespaceMembersIndexContext() : RefCountedContext("NamespaceMembersIndexContext")
8427 {
8428   p = new Private;
8429 }
8430
8431 NamespaceMembersIndexContext::~NamespaceMembersIndexContext()
8432 {
8433   delete p;
8434 }
8435
8436 TemplateVariant NamespaceMembersIndexContext::get(const char *name) const
8437 {
8438   return p->get(name);
8439 }
8440
8441 //------------------------------------------------------------------------
8442
8443 //%% struct InheritanceGraph: a connected graph reprenting part of the overall interitance tree
8444 //%% {
8445 class InheritanceGraphContext::Private
8446 {
8447   public:
8448     Private(DotGfxHierarchyTable *hierarchy,DotNode *n,int id) : m_hierarchy(hierarchy), m_node(n), m_id(id)
8449     {
8450       static bool init=FALSE;
8451       if (!init)
8452       {
8453         s_inst.addProperty("graph",&Private::graph);
8454         init=TRUE;
8455       }
8456     }
8457     TemplateVariant get(const char *n) const
8458     {
8459       return s_inst.get(this,n);
8460     }
8461     TemplateVariant graph() const
8462     {
8463       QGString result;
8464       static bool haveDot            = Config_getBool(HAVE_DOT);
8465       static bool graphicalHierarchy = Config_getBool(GRAPHICAL_HIERARCHY);
8466       if (haveDot && graphicalHierarchy)
8467       {
8468         FTextStream t(&result);
8469         m_hierarchy->createGraph(m_node,t,
8470                           /*GOF_BITMAP,
8471                           EOF_Html,*/
8472                           g_globals.outputDir,
8473                           g_globals.outputDir+portable_pathSeparator()+"inherits"+Doxygen::htmlFileExtension,
8474                           m_id);
8475       }
8476       return TemplateVariant(result.data(),TRUE);
8477     }
8478   private:
8479     DotGfxHierarchyTable *m_hierarchy;
8480     DotNode *m_node;
8481     int m_id;
8482     static PropertyMapper<InheritanceGraphContext::Private> s_inst;
8483 };
8484
8485 PropertyMapper<InheritanceGraphContext::Private> InheritanceGraphContext::Private::s_inst;
8486
8487 InheritanceGraphContext::InheritanceGraphContext(DotGfxHierarchyTable *hierarchy,DotNode *n,int id)
8488    : RefCountedContext("InheritanceGraphContext")
8489 {
8490   p = new Private(hierarchy,n,id);
8491 }
8492
8493 InheritanceGraphContext::~InheritanceGraphContext()
8494 {
8495   delete p;
8496 }
8497
8498 TemplateVariant InheritanceGraphContext::get(const char *name) const
8499 {
8500   return p->get(name);
8501 }
8502
8503
8504 //------------------------------------------------------------------------
8505
8506 //%% struct InheritanceNode: a class in the inheritance list
8507 //%% {
8508 class InheritanceNodeContext::Private
8509 {
8510   public:
8511     Private(ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name)
8512     {
8513       static bool init=FALSE;
8514       if (!init)
8515       {
8516         s_inst.addProperty("class",&Private::getClass);
8517         s_inst.addProperty("name", &Private::name);
8518         init=TRUE;
8519       }
8520     }
8521     TemplateVariant get(const char *n) const
8522     {
8523       return s_inst.get(this,n);
8524     }
8525     TemplateVariant getClass() const
8526     {
8527       if (!m_classContext)
8528       {
8529         m_classContext.reset(ClassContext::alloc(m_classDef));
8530       }
8531       return m_classContext.get();
8532     }
8533     TemplateVariant name() const
8534     {
8535       return m_name;
8536     }
8537   private:
8538     ClassDef *m_classDef;
8539     mutable SharedPtr<ClassContext> m_classContext;
8540     QCString m_name;
8541     static PropertyMapper<InheritanceNodeContext::Private> s_inst;
8542 };
8543 //%% }
8544
8545 PropertyMapper<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst;
8546
8547 InheritanceNodeContext::InheritanceNodeContext(ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext")
8548 {
8549   p = new Private(cd,name);
8550 }
8551
8552 InheritanceNodeContext::~InheritanceNodeContext()
8553 {
8554   delete p;
8555 }
8556
8557 TemplateVariant InheritanceNodeContext::get(const char *name) const
8558 {
8559   return p->get(name);
8560 }
8561
8562 //------------------------------------------------------------------------
8563
8564 //%% list InheritanceList[InheritanceNode] : list of inherited classes
8565 class InheritanceListContext::Private : public GenericNodeListContext
8566 {
8567   public:
8568     void addClass(ClassDef *cd,const QCString &name)
8569     {
8570       append(InheritanceNodeContext::alloc(cd,name));
8571     }
8572 };
8573
8574 InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool baseClasses) : RefCountedContext("InheritanceListContext")
8575 {
8576   p = new Private;
8577   if (list)
8578   {
8579     BaseClassListIterator li(*list);
8580     BaseClassDef *bcd;
8581     for (li.toFirst();(bcd=li.current());++li)
8582     {
8583       ClassDef *cd=bcd->classDef;
8584       QCString name;
8585       if (baseClasses)
8586       {
8587         name = insertTemplateSpecifierInScope(
8588                      cd->displayName(),bcd->templSpecifiers);
8589       }
8590       else
8591       {
8592         name = cd->displayName();
8593       }
8594       //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses);
8595       p->addClass(cd,name);
8596     }
8597   }
8598 }
8599
8600 InheritanceListContext::~InheritanceListContext()
8601 {
8602   delete p;
8603 }
8604
8605 // TemplateListIntf
8606 int InheritanceListContext::count() const
8607 {
8608   return p->count();
8609 }
8610
8611 TemplateVariant InheritanceListContext::at(int index) const
8612 {
8613   return p->at(index);
8614 }
8615
8616 TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const
8617 {
8618   return p->createIterator();
8619 }
8620
8621 //------------------------------------------------------------------------
8622
8623 //%% list MemberList[Member] : list of inherited classes
8624 class MemberListContext::Private : public GenericNodeListContext
8625 {
8626   public:
8627     void addMember(MemberDef *md)
8628     {
8629       append(MemberContext::alloc(md));
8630     }
8631 };
8632
8633 MemberListContext::MemberListContext() : RefCountedContext("MemberListContext")
8634 {
8635   p = new Private;
8636 }
8637
8638 MemberListContext::MemberListContext(const MemberList *list) : RefCountedContext("MemberListContext")
8639 {
8640   p = new Private;
8641   if (list)
8642   {
8643     bool details = list->listType()&MemberListType_detailedLists;
8644     MemberListIterator mli(*list);
8645     MemberDef *md;
8646     for (mli.toFirst();(md=mli.current());++mli)
8647     {
8648       if ((md->isBriefSectionVisible() && !details) ||
8649           (md->isDetailedSectionLinkable() && details)
8650          )
8651       {
8652         p->addMember(md);
8653       }
8654     }
8655   }
8656 }
8657
8658 MemberListContext::MemberListContext(MemberSDict *list,bool doSort) : RefCountedContext("MemberListContext")
8659 {
8660   p = new Private;
8661   if (list)
8662   {
8663     if (doSort)
8664     {
8665       list->sort();
8666     }
8667     MemberSDict::Iterator it(*list);
8668     MemberDef *md;
8669     for (it.toFirst();(md=it.current());++it)
8670     {
8671       p->addMember(md);
8672     }
8673   }
8674 }
8675
8676 MemberListContext::~MemberListContext()
8677 {
8678   delete p;
8679 }
8680
8681 // TemplateListIntf
8682 int MemberListContext::count() const
8683 {
8684   return p->count();
8685 }
8686
8687 TemplateVariant MemberListContext::at(int index) const
8688 {
8689   return p->at(index);
8690 }
8691
8692 TemplateListIntf::ConstIterator *MemberListContext::createIterator() const
8693 {
8694   return p->createIterator();
8695 }
8696
8697 //------------------------------------------------------------------------
8698
8699 //%% struct MemberInfo: member information
8700 //%% {
8701 class MemberInfoContext::Private
8702 {
8703   public:
8704     Private(const MemberInfo *mi) : m_memberInfo(mi)
8705     {
8706       static bool init=FALSE;
8707       if (!init)
8708       {
8709         //%% string protection
8710         s_inst.addProperty("protection",    &Private::protection);
8711         //%% string virtualness
8712         s_inst.addProperty("virtualness",   &Private::virtualness);
8713         //%% string ambiguityScope
8714         s_inst.addProperty("ambiguityScope",&Private::ambiguityScope);
8715         //%% Member member
8716         s_inst.addProperty("member",        &Private::member);
8717         init=TRUE;
8718       }
8719     }
8720     TemplateVariant get(const char *n) const
8721     {
8722       return s_inst.get(this,n);
8723     }
8724     TemplateVariant protection() const
8725     {
8726       switch (m_memberInfo->prot)
8727       {
8728         case ::Public:    return "public";
8729         case ::Protected: return "protected";
8730         case ::Private:   return "private";
8731         case ::Package:   return "package";
8732       }
8733       return "";
8734     }
8735     TemplateVariant virtualness() const
8736     {
8737       switch (m_memberInfo->virt)
8738       {
8739         case ::Normal:   return "normal";
8740         case ::Virtual:  return "virtual";
8741         case ::Pure:     return "pure";
8742       }
8743       return "";
8744     }
8745     TemplateVariant ambiguityScope() const
8746     {
8747       return m_memberInfo->ambiguityResolutionScope;
8748     }
8749     TemplateVariant member() const
8750     {
8751       if (!m_member && m_memberInfo->memberDef)
8752       {
8753         m_member.reset(MemberContext::alloc(m_memberInfo->memberDef));
8754       }
8755       if (m_member)
8756       {
8757         return m_member.get();
8758       }
8759       else
8760       {
8761         return TemplateVariant(FALSE);
8762       }
8763     }
8764   private:
8765     const MemberInfo *m_memberInfo;
8766     mutable SharedPtr<MemberContext> m_member;
8767     static PropertyMapper<MemberInfoContext::Private> s_inst;
8768 };
8769 //%% }
8770
8771 PropertyMapper<MemberInfoContext::Private> MemberInfoContext::Private::s_inst;
8772
8773 MemberInfoContext::MemberInfoContext(const MemberInfo *mi) : RefCountedContext("MemberInfoContext")
8774 {
8775   p = new Private(mi);
8776 }
8777
8778 MemberInfoContext::~MemberInfoContext()
8779 {
8780   delete p;
8781 }
8782
8783 TemplateVariant MemberInfoContext::get(const char *name) const
8784 {
8785   return p->get(name);
8786 }
8787
8788
8789 //------------------------------------------------------------------------
8790
8791 //%% list AllMembersList[MemberList] : list of inherited classes
8792 class AllMembersListContext::Private : public GenericNodeListContext
8793 {
8794   public:
8795     Private(const MemberNameInfoSDict *ml)
8796     {
8797       if (ml)
8798       {
8799         static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
8800         MemberNameInfoSDict::Iterator mnii(*ml);
8801         MemberNameInfo *mni;
8802         for (mnii.toFirst();(mni=mnii.current());++mnii)
8803         {
8804           MemberNameInfoIterator mnii2(*mni);
8805           MemberInfo *mi;
8806           for (mnii2.toFirst();(mi=mnii2.current());++mnii2)
8807           {
8808             MemberDef *md=mi->memberDef;
8809             ClassDef  *cd=md->getClassDef();
8810             if (cd && !md->name().isEmpty() && md->name()[0]!='@')
8811             {
8812               if ((cd->isLinkable() && md->isLinkable()) ||
8813                   (!cd->isArtificial() && !hideUndocMembers &&
8814                    (protectionLevelVisible(md->protection()) || md->isFriend())
8815                   )
8816                  )
8817               {
8818                 append(MemberInfoContext::alloc(mi));
8819               }
8820             }
8821           }
8822         }
8823       }
8824     }
8825 };
8826
8827 AllMembersListContext::AllMembersListContext() : RefCountedContext("AllMembersListContext")
8828 {
8829   p = new Private(0);
8830 }
8831
8832 AllMembersListContext::AllMembersListContext(const MemberNameInfoSDict *ml) : RefCountedContext("AllMembersListContext")
8833 {
8834   p = new Private(ml);
8835 }
8836
8837 AllMembersListContext::~AllMembersListContext()
8838 {
8839   delete p;
8840 }
8841
8842 // TemplateListIntf
8843 int AllMembersListContext::count() const
8844 {
8845   return p->count();
8846 }
8847
8848 TemplateVariant AllMembersListContext::at(int index) const
8849 {
8850   return p->at(index);
8851 }
8852
8853 TemplateListIntf::ConstIterator *AllMembersListContext::createIterator() const
8854 {
8855   return p->createIterator();
8856 }
8857
8858 //------------------------------------------------------------------------
8859
8860 //%% struct MemberGroupInfo: member group information
8861 //%% {
8862 class MemberGroupInfoContext::Private
8863 {
8864   public:
8865     Private(Definition *def,const QCString &relPath,const MemberGroup *mg) :
8866       m_def(def),
8867       m_relPath(relPath),
8868       m_memberGroup(mg)
8869     {
8870       static bool init=FALSE;
8871       if (!init)
8872       {
8873         s_inst.addProperty("members",      &Private::members);
8874         s_inst.addProperty("title",        &Private::groupTitle);
8875         s_inst.addProperty("subtitle",     &Private::groupSubtitle);
8876         s_inst.addProperty("anchor",       &Private::groupAnchor);
8877         s_inst.addProperty("memberGroups", &Private::memberGroups);
8878         s_inst.addProperty("docs",         &Private::docs);
8879         s_inst.addProperty("inherited",    &Private::inherited);
8880         init=TRUE;
8881       }
8882     }
8883     TemplateVariant get(const char *n) const
8884     {
8885       return s_inst.get(this,n);
8886     }
8887     TemplateVariant members() const
8888     {
8889       if (!m_cache.memberListContext)
8890       {
8891         m_cache.memberListContext.reset(MemberListContext::alloc(m_memberGroup->members()));
8892       }
8893       return m_cache.memberListContext.get();
8894     }
8895     TemplateVariant groupTitle() const
8896     {
8897       return m_memberGroup->header();
8898     }
8899     TemplateVariant groupSubtitle() const
8900     {
8901       return "";
8902     }
8903     TemplateVariant groupAnchor() const
8904     {
8905       return m_memberGroup->anchor();
8906     }
8907     TemplateVariant memberGroups() const
8908     {
8909       if (!m_cache.memberGroups)
8910       {
8911         m_cache.memberGroups.reset(MemberGroupListContext::alloc(m_def,m_relPath,0));
8912       }
8913       return m_cache.memberGroups.get();
8914     }
8915     TemplateVariant docs() const
8916     {
8917       if (!m_cache.docs)
8918       {
8919         QCString docs = m_memberGroup->documentation();
8920         if (!docs.isEmpty())
8921         {
8922           m_cache.docs.reset(new TemplateVariant(
8923                            parseDoc(m_def,"[@name docs]",-1, // TODO store file & line
8924                                     m_relPath,
8925                                     m_memberGroup->documentation()+"\n",FALSE)));
8926         }
8927         else
8928         {
8929           m_cache.docs.reset(new TemplateVariant(""));
8930         }
8931       }
8932       return *m_cache.docs;
8933     }
8934     TemplateVariant inherited() const
8935     {
8936       return FALSE;
8937     }
8938   private:
8939     Definition *m_def;
8940     QCString m_relPath;
8941     const MemberGroup *m_memberGroup;
8942     struct Cachable
8943     {
8944       SharedPtr<MemberListContext>      memberListContext;
8945       SharedPtr<MemberGroupListContext> memberGroups;
8946       ScopedPtr<TemplateVariant>        docs;
8947     };
8948     mutable Cachable m_cache;
8949     static PropertyMapper<MemberGroupInfoContext::Private> s_inst;
8950 };
8951 //%% }
8952
8953 PropertyMapper<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst;
8954
8955 MemberGroupInfoContext::MemberGroupInfoContext(Definition *def,
8956        const QCString &relPath,const MemberGroup *mg) : RefCountedContext("MemberGroupInfoContext")
8957 {
8958   p = new Private(def,relPath,mg);
8959 }
8960
8961 MemberGroupInfoContext::~MemberGroupInfoContext()
8962 {
8963   delete p;
8964 }
8965
8966 TemplateVariant MemberGroupInfoContext::get(const char *name) const
8967 {
8968   return p->get(name);
8969 }
8970
8971 //------------------------------------------------------------------------
8972
8973 //%% list MemberGroupList[MemberGroupInfo] : list of member groups
8974 class MemberGroupListContext::Private : public GenericNodeListContext
8975 {
8976   public:
8977     void addMemberGroup(Definition *def,const QCString &relPath,const MemberGroup *mg)
8978     {
8979       append(MemberGroupInfoContext::alloc(def,relPath,mg));
8980     }
8981 };
8982
8983 MemberGroupListContext::MemberGroupListContext() : RefCountedContext("MemberGroupListContext")
8984 {
8985   p = new Private;
8986 }
8987
8988 MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupList *list) : RefCountedContext("MemberGroupListContext")
8989 {
8990   p = new Private;
8991   if (list)
8992   {
8993     MemberGroupListIterator mgli(*list);
8994     MemberGroup *mg;
8995     for (;(mg=mgli.current());++mgli)
8996     {
8997       p->addMemberGroup(def,relPath,mg);
8998     }
8999   }
9000 }
9001
9002 MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) : RefCountedContext("MemberGroupListContext")
9003 {
9004   p = new Private;
9005   if (dict)
9006   {
9007     MemberGroupSDict::Iterator di(*dict);
9008     const MemberGroup *mg;
9009     for (di.toFirst();(mg=di.current());++di)
9010     {
9011       if (!mg->allMembersInSameSection() || !subGrouping)
9012       {
9013         p->addMemberGroup(def,relPath,mg);
9014       }
9015     }
9016   }
9017 }
9018
9019 MemberGroupListContext::~MemberGroupListContext()
9020 {
9021   delete p;
9022 }
9023
9024 // TemplateListIntf
9025 int MemberGroupListContext::count() const
9026 {
9027   return p->count();
9028 }
9029
9030 TemplateVariant MemberGroupListContext::at(int index) const
9031 {
9032   return p->at(index);
9033 }
9034
9035 TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const
9036 {
9037   return p->createIterator();
9038 }
9039
9040
9041 //------------------------------------------------------------------------
9042
9043 //%% struct MemberListInfo: member list information
9044 //%% {
9045 class MemberListInfoContext::Private
9046 {
9047   public:
9048     Private(Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) :
9049       m_def(def),
9050       m_memberList(ml),
9051       m_relPath(relPath),
9052       m_title(title),
9053       m_subtitle(subtitle)
9054     {
9055       static bool init=FALSE;
9056       if (!init)
9057       {
9058         s_inst.addProperty("members",      &Private::members);
9059         s_inst.addProperty("title",        &Private::title);
9060         s_inst.addProperty("subtitle",     &Private::subtitle);
9061         s_inst.addProperty("anchor",       &Private::anchor);
9062         s_inst.addProperty("memberGroups", &Private::memberGroups);
9063         s_inst.addProperty("inherited",    &Private::inherited);
9064         init=TRUE;
9065       }
9066     }
9067     TemplateVariant get(const char *n) const
9068     {
9069       return s_inst.get(this,n);
9070     }
9071     TemplateVariant members() const
9072     {
9073       if (!m_cache.memberListContext)
9074       {
9075         m_cache.memberListContext.reset(MemberListContext::alloc(m_memberList));
9076       }
9077       return m_cache.memberListContext.get();
9078     }
9079     TemplateVariant title() const
9080     {
9081       return m_title;
9082     }
9083     TemplateVariant subtitle() const
9084     {
9085       return m_subtitle;
9086     }
9087     TemplateVariant anchor() const
9088     {
9089       return MemberList::listTypeAsString(m_memberList->listType());
9090     }
9091     TemplateVariant memberGroups() const
9092     {
9093       if (!m_cache.memberGroups)
9094       {
9095         m_cache.memberGroups.reset(MemberGroupListContext::alloc(m_def,m_relPath,m_memberList->getMemberGroupList()));
9096       }
9097       return m_cache.memberGroups.get();
9098     }
9099     TemplateVariant inherited() const
9100     {
9101       if (!m_cache.inherited && (m_memberList->listType()&MemberListType_detailedLists)==0 &&
9102           m_def->definitionType()==Definition::TypeClass)
9103       {
9104         InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc();
9105         ctx->addMemberList((ClassDef*)m_def,m_memberList->listType(),m_title,FALSE);
9106         m_cache.inherited.reset(ctx);
9107       }
9108       if (m_cache.inherited)
9109       {
9110         return m_cache.inherited.get();
9111       }
9112       else
9113       {
9114         return TemplateVariant(FALSE);
9115       }
9116     }
9117   private:
9118     Definition *m_def;
9119     const MemberList *m_memberList;
9120     QCString m_relPath;
9121     QCString m_title;
9122     QCString m_subtitle;
9123     struct Cachable
9124     {
9125       SharedPtr<MemberListContext> memberListContext;
9126       SharedPtr<MemberGroupListContext> memberGroups;
9127       SharedPtr<InheritedMemberInfoListContext> inherited;
9128     };
9129     mutable Cachable m_cache;
9130     static PropertyMapper<MemberListInfoContext::Private> s_inst;
9131 };
9132 //%% }
9133
9134 PropertyMapper<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst;
9135
9136 MemberListInfoContext::MemberListInfoContext(
9137            Definition *def,const QCString &relPath,const MemberList *ml,
9138            const QCString &title,const QCString &subtitle) : RefCountedContext("MemberListInfoContext")
9139 {
9140   p = new Private(def,relPath,ml,title,subtitle);
9141 }
9142
9143 MemberListInfoContext::~MemberListInfoContext()
9144 {
9145   delete p;
9146 }
9147
9148 TemplateVariant MemberListInfoContext::get(const char *name) const
9149 {
9150   return p->get(name);
9151 }
9152
9153 //------------------------------------------------------------------------
9154
9155 //%% struct InheritedMemberInfo: inherited member information
9156 //%% {
9157 class InheritedMemberInfoContext::Private
9158 {
9159   public:
9160     Private(ClassDef *cd,MemberList *ml,const QCString &title)
9161       : m_class(cd), m_memberList(ml), m_title(title)
9162     {
9163       static bool init=FALSE;
9164       if (!init)
9165       {
9166         s_inst.addProperty("class",         &Private::getClass);
9167         s_inst.addProperty("title",         &Private::title);
9168         s_inst.addProperty("members",       &Private::members);
9169         s_inst.addProperty("id",            &Private::id);
9170         s_inst.addProperty("inheritedFrom", &Private::inheritedFrom);
9171         init=TRUE;
9172       }
9173     }
9174     TemplateVariant get(const char *n) const
9175     {
9176       return s_inst.get(this,n);
9177     }
9178     virtual ~Private()
9179     {
9180       delete m_memberList;
9181     }
9182     TemplateVariant getClass() const
9183     {
9184       if (!m_classCtx)
9185       {
9186         m_classCtx.reset(ClassContext::alloc(m_class));
9187       }
9188       return m_classCtx.get();
9189     }
9190     TemplateVariant title() const
9191     {
9192       return m_title;
9193     }
9194     TemplateVariant members() const
9195     {
9196       if (!m_memberListCtx)
9197       {
9198         m_memberListCtx.reset(MemberListContext::alloc(m_memberList));
9199       }
9200       return m_memberListCtx.get();
9201     }
9202     TemplateVariant id() const
9203     {
9204       return substitute(MemberList::listTypeAsString(m_memberList->listType()),"-","_")+"_"+
9205                         stripPath(m_class->getOutputFileBase());
9206     }
9207     TemplateVariant inheritedFrom() const
9208     {
9209       if (!m_inheritedFrom)
9210       {
9211         m_inheritedFrom.reset(TemplateList::alloc());
9212         m_inheritedFrom->append(title());
9213         m_inheritedFrom->append(getClass());
9214       }
9215       return m_inheritedFrom.get();
9216     }
9217
9218   private:
9219     ClassDef *  m_class;
9220     MemberList *m_memberList;
9221     QCString    m_title;
9222     mutable SharedPtr<ClassContext> m_classCtx;
9223     mutable SharedPtr<MemberListContext> m_memberListCtx;
9224     mutable SharedPtr<TemplateList> m_inheritedFrom;
9225     static PropertyMapper<InheritedMemberInfoContext::Private> s_inst;
9226 };
9227 //%% }
9228
9229 PropertyMapper<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst;
9230
9231 InheritedMemberInfoContext::InheritedMemberInfoContext(ClassDef *cd,MemberList *ml,
9232                                                        const QCString &title) : RefCountedContext("InheritedMemberInfoContext")
9233 {
9234   p = new Private(cd,ml,title);
9235 }
9236
9237 InheritedMemberInfoContext::~InheritedMemberInfoContext()
9238 {
9239   delete p;
9240 }
9241
9242 TemplateVariant InheritedMemberInfoContext::get(const char *name) const
9243 {
9244   return p->get(name);
9245 }
9246
9247 //------------------------------------------------------------------------
9248
9249 //%% list InheritedMemberList[InheritedMemberInfo] : list of inherited classes
9250 class InheritedMemberInfoListContext::Private : public GenericNodeListContext
9251 {
9252   public:
9253     void addMemberList(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
9254     {
9255       if (ml)
9256       {
9257         MemberListIterator li(*ml);
9258         MemberDef *md;
9259         for (li.toFirst();(md=li.current());++li)
9260         {
9261           if (md->isBriefSectionVisible() && !md->isReimplementedBy(inheritedFrom))
9262           {
9263             combinedList->append(md);
9264           }
9265         }
9266       }
9267     }
9268     void addMemberListIncludingGrouped(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
9269     {
9270       if (ml)
9271       {
9272         addMemberList(inheritedFrom,ml,combinedList);
9273         if (ml->getMemberGroupList())
9274         {
9275           MemberGroupListIterator mgli(*ml->getMemberGroupList());
9276           MemberGroup *mg;
9277           for (mgli.toFirst();(mg=mgli.current());++mgli)
9278           {
9279             addMemberList(inheritedFrom,mg->members(),combinedList);
9280           }
9281         }
9282       }
9283     }
9284     void addMemberGroupsOfClass(ClassDef *inheritedFrom,
9285                                 ClassDef *cd,MemberListType lt,MemberList *combinedList)
9286     {
9287       if (cd->getMemberGroupSDict())
9288       {
9289         MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
9290         MemberGroup *mg;
9291         for (;(mg=mgli.current());++mgli)
9292         {
9293           if (mg->members() && (!mg->allMembersInSameSection() || !cd->subGrouping())) // group is in its own section
9294           {
9295             MemberListIterator li(*mg->members());
9296             MemberDef *md;
9297             for (li.toFirst();(md=li.current());++li)
9298             {
9299               if (lt==md->getSectionList(mg->parent())->listType() &&
9300                   !md->isReimplementedBy(inheritedFrom) &&
9301                   md->isBriefSectionVisible())
9302               {
9303                 combinedList->append(md);
9304               }
9305             }
9306           }
9307         }
9308       }
9309     }
9310     void addInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt,
9311                              MemberListType lt1,int lt2,const QCString &title,bool additionalList)
9312     {
9313       int count = cd->countMembersIncludingGrouped(lt1,inheritedFrom,additionalList);
9314       if (lt2!=-1) count += cd->countMembersIncludingGrouped((MemberListType)lt2,inheritedFrom,additionalList);
9315       if (count>0)
9316       {
9317         MemberList *ml  = cd->getMemberList(lt1);
9318         MemberList *ml2 = lt2!=-1 ? cd->getMemberList((MemberListType)lt2) : 0;
9319         MemberList *combinedList = new MemberList(lt);
9320         addMemberListIncludingGrouped(inheritedFrom,ml,combinedList);
9321         addMemberListIncludingGrouped(inheritedFrom,ml2,combinedList);
9322         addMemberGroupsOfClass(inheritedFrom,cd,lt,combinedList);
9323         if (lt2!=-1) addMemberGroupsOfClass(inheritedFrom,cd,(MemberListType)lt2,combinedList);
9324         append(InheritedMemberInfoContext::alloc(cd,combinedList,title));
9325       }
9326     }
9327     void findInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt,
9328                               int lt2, const QCString &title,bool additionalList,
9329                               QPtrDict<void> *visitedClasses)
9330     {
9331       if (cd->baseClasses())
9332       {
9333         BaseClassListIterator it(*cd->baseClasses());
9334         BaseClassDef *ibcd;
9335         for (it.toFirst();(ibcd=it.current());++it)
9336         {
9337           ClassDef *icd=ibcd->classDef;
9338           if (icd->isLinkable())
9339           {
9340             int lt1,lt3;
9341             convertProtectionLevel(lt,ibcd->prot,&lt1,&lt3);
9342             if (lt2==-1 && lt3!=-1)
9343             {
9344               lt2=lt3;
9345             }
9346             if (visitedClasses->find(icd)==0)
9347             {
9348               visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance
9349               if (lt1!=-1)
9350               {
9351                 // add member info for members of cd with list type lt
9352                 addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList);
9353                 // recurse down the inheritance tree
9354                 findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses);
9355               }
9356             }
9357           }
9358         }
9359       }
9360     }
9361 };
9362
9363 InheritedMemberInfoListContext::InheritedMemberInfoListContext() : RefCountedContext("InheritedMemberInfoListContext")
9364 {
9365   p = new Private;
9366 }
9367
9368 void InheritedMemberInfoListContext::addMemberList(
9369     ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList)
9370 {
9371   QPtrDict<void> visited(17);
9372   bool memberInSection = cd->countMembersIncludingGrouped(lt,cd,FALSE)>0;
9373   bool show = (additionalList && !memberInSection) || // inherited member to show in the additional inherited members list
9374               (!additionalList && memberInSection);   // inherited member to show in a member list of the class
9375   //printf("%s:%s show=%d\n",cd->name().data(),MemberList::listTypeAsString(lt).data(),show);
9376   if (show)
9377   {
9378     p->findInheritedMembers(cd,cd,lt,-1,title,additionalList,&visited);
9379   }
9380 }
9381
9382 InheritedMemberInfoListContext::~InheritedMemberInfoListContext()
9383 {
9384   delete p;
9385 }
9386
9387 // TemplateListIntf
9388 int InheritedMemberInfoListContext::count() const
9389 {
9390   return p->count();
9391 }
9392
9393 TemplateVariant InheritedMemberInfoListContext::at(int index) const
9394 {
9395   return p->at(index);
9396 }
9397
9398 TemplateListIntf::ConstIterator *InheritedMemberInfoListContext::createIterator() const
9399 {
9400   return p->createIterator();
9401 }
9402
9403 //------------------------------------------------------------------------
9404
9405 //%% struct Argument: parameter information
9406 //%% {
9407 class ArgumentContext::Private
9408 {
9409   public:
9410     Private(const Argument *arg,Definition *def,const QCString &relPath) :
9411       m_argument(arg), m_def(def), m_relPath(relPath)
9412     {
9413       static bool init=FALSE;
9414       if (!init)
9415       {
9416         s_inst.addProperty("type",     &Private::type);
9417         s_inst.addProperty("name",     &Private::name);
9418         s_inst.addProperty("defVal",   &Private::defVal);
9419         s_inst.addProperty("docs",     &Private::docs);
9420         s_inst.addProperty("attrib",   &Private::attrib);
9421         s_inst.addProperty("array",    &Private::array);
9422         s_inst.addProperty("namePart", &Private::namePart);
9423         init=TRUE;
9424       }
9425     }
9426     TemplateVariant get(const char *n) const
9427     {
9428       return s_inst.get(this,n);
9429     }
9430     TemplateVariant type() const
9431     {
9432       return createLinkedText(m_def,m_relPath,m_argument->type);
9433     }
9434     TemplateVariant attrib() const
9435     {
9436       return m_argument->attrib;
9437     }
9438     TemplateVariant name() const
9439     {
9440       return m_argument->name;
9441     }
9442     TemplateVariant defVal() const
9443     {
9444       return createLinkedText(m_def,m_relPath,m_argument->defval);
9445     }
9446     TemplateVariant array() const
9447     {
9448       return m_argument->array;
9449     }
9450     TemplateVariant docs() const
9451     {
9452       if (!m_cache.docs && m_def)
9453       {
9454         if (!m_argument->docs.isEmpty())
9455         {
9456           m_cache.docs.reset(new TemplateVariant(
9457                              parseDoc(m_def,m_def->docFile(),m_def->docLine(),
9458                              m_relPath,m_argument->docs,TRUE)));
9459         }
9460         else
9461         {
9462           m_cache.docs.reset(new TemplateVariant(""));
9463         }
9464       }
9465       return *m_cache.docs;
9466     }
9467     TemplateVariant namePart() const
9468     {
9469       QCString result = m_argument->attrib;
9470       int l = result.length();
9471       if (l>2 && result.at(0)=='[' && result.at(l-1)==']')
9472       {
9473         result = result.mid(1,l-2);
9474         if (result!=",") result+=":"; // for normal keywords add colon
9475       }
9476       return result;
9477     }
9478   private:
9479     const Argument *m_argument;
9480     Definition *m_def;
9481     QCString m_relPath;
9482     struct Cachable
9483     {
9484       ScopedPtr<TemplateVariant> docs;
9485     };
9486     mutable Cachable m_cache;
9487     static PropertyMapper<ArgumentContext::Private> s_inst;
9488 };
9489 //%% }
9490
9491 PropertyMapper<ArgumentContext::Private> ArgumentContext::Private::s_inst;
9492
9493 ArgumentContext::ArgumentContext(const Argument *al,Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext")
9494 {
9495   p = new Private(al,def,relPath);
9496 }
9497
9498 ArgumentContext::~ArgumentContext()
9499 {
9500   delete p;
9501 }
9502
9503 TemplateVariant ArgumentContext::get(const char *name) const
9504 {
9505   return p->get(name);
9506 }
9507
9508 //------------------------------------------------------------------------
9509
9510 //%% list ArgumentList[Argument] : list of inherited classes
9511 class ArgumentListContext::Private : public GenericNodeListContext
9512 {
9513   public:
9514     void addArgument(const Argument *arg,Definition *def,const QCString &relPath)
9515     {
9516       append(ArgumentContext::alloc(arg,def,relPath));
9517     }
9518 };
9519
9520 ArgumentListContext::ArgumentListContext() : RefCountedContext("ArgumentListContext")
9521 {
9522   p = new Private;
9523 }
9524
9525 ArgumentListContext::ArgumentListContext(const ArgumentList *list,
9526                         Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext")
9527 {
9528   p = new Private;
9529   if (list)
9530   {
9531     ArgumentListIterator ali(*list);
9532     const Argument *arg;
9533     for (ali.toFirst();(arg=ali.current());++ali)
9534     {
9535       p->addArgument(arg,def,relPath);
9536     }
9537   }
9538 }
9539
9540 ArgumentListContext::~ArgumentListContext()
9541 {
9542   delete p;
9543 }
9544
9545 // TemplateListIntf
9546 int ArgumentListContext::count() const
9547 {
9548   return p->count();
9549 }
9550
9551 TemplateVariant ArgumentListContext::at(int index) const
9552 {
9553   return p->at(index);
9554 }
9555
9556 TemplateListIntf::ConstIterator *ArgumentListContext::createIterator() const
9557 {
9558   return p->createIterator();
9559 }
9560
9561 //------------------------------------------------------------------------
9562
9563 // SymbolIndex
9564 //  - name: string
9565 //  - letter: string
9566 //  - symbolGroups: SymbolGroupList
9567 // SymbolGroupList: list of SymbolGroups
9568 // SymbolGroup
9569 //  - id
9570 //  - name
9571 //  - symbols: SymbolList
9572 // SymbolList: list of Symbols
9573 // Symbol
9574 //  - obj
9575 //  - scope
9576 //  - relPath
9577
9578 //------------------------------------------------------------------------
9579
9580 //%% struct SymbolGroup: search group of similar symbols
9581 //%% {
9582 class SymbolContext::Private
9583 {
9584   public:
9585     Private(const Definition *d,const Definition *prev,
9586             const Definition *next) : m_def(d), m_prevDef(prev), m_nextDef(next)
9587     {
9588       static bool init=FALSE;
9589       if (!init)
9590       {
9591         s_inst.addProperty("fileName",&Private::fileName);
9592         s_inst.addProperty("anchor",  &Private::anchor);
9593         s_inst.addProperty("scope",   &Private::scope);
9594         s_inst.addProperty("relPath", &Private::relPath);
9595         init=TRUE;
9596       }
9597     }
9598     TemplateVariant get(const char *n) const
9599     {
9600       return s_inst.get(this,n);
9601     }
9602     TemplateVariant fileName() const
9603     {
9604       return m_def->getOutputFileBase();
9605     }
9606     TemplateVariant anchor() const
9607     {
9608       return m_def->anchor();
9609     }
9610     TemplateVariant scope() const
9611     {
9612       const Definition *scope     = m_def->getOuterScope();
9613       const Definition *next      = m_nextDef;
9614       const Definition *prev      = m_prevDef;
9615       const Definition *nextScope = next ? next->getOuterScope() : 0;
9616       const Definition *prevScope = prev ? prev->getOuterScope() : 0;
9617       bool isMemberDef            = m_def->definitionType()==Definition::TypeMember;
9618       const MemberDef  *md        = isMemberDef ? (const MemberDef*)m_def : 0;
9619       bool isFunctionLike   = md && (md->isFunction() || md->isSlot() || md->isSignal());
9620       bool overloadedFunction = isFunctionLike &&
9621                                 ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope));
9622       QCString prefix;
9623       if (md) prefix=md->localName();
9624       if (overloadedFunction) // overloaded member function
9625       {
9626         prefix+=md->argsString();
9627         // show argument list to disambiguate overloaded functions
9628       }
9629       else if (md && isFunctionLike) // unique member function
9630       {
9631         prefix+="()"; // only to show it is a function
9632       }
9633       bool found=FALSE;
9634       QCString name;
9635       if (m_def->definitionType()==Definition::TypeClass)
9636       {
9637         name = m_def->displayName();
9638         found = TRUE;
9639       }
9640       else if (m_def->definitionType()==Definition::TypeNamespace)
9641       {
9642         name = m_def->displayName();
9643         found = TRUE;
9644       }
9645       else if (scope==0 || scope==Doxygen::globalScope) // in global scope
9646       {
9647         if (md)
9648         {
9649           FileDef *fd = md->getBodyDef();
9650           if (fd==0) fd = md->getFileDef();
9651           if (fd)
9652           {
9653             if (!prefix.isEmpty()) prefix+=": ";
9654             name = prefix + convertToXML(fd->localName());
9655             found = TRUE;
9656           }
9657         }
9658       }
9659       else if (md && (md->getClassDef() || md->getNamespaceDef()))
9660         // member in class or namespace scope
9661       {
9662         SrcLangExt lang = md->getLanguage();
9663         name = m_def->getOuterScope()->qualifiedName()
9664           + getLanguageSpecificSeparator(lang) + prefix;
9665         found = TRUE;
9666       }
9667       else if (scope) // some thing else? -> show scope
9668       {
9669         name = prefix + convertToXML(scope->name());
9670         found = TRUE;
9671       }
9672       if (!found) // fallback
9673       {
9674         name = prefix + "("+theTranslator->trGlobalNamespace()+")";
9675       }
9676       return name;
9677     }
9678     TemplateVariant relPath() const
9679     {
9680       return externalRef("../",m_def->getReference(),TRUE);
9681     }
9682   private:
9683     const Definition *m_def;
9684     const Definition *m_prevDef;
9685     const Definition *m_nextDef;
9686     static PropertyMapper<SymbolContext::Private> s_inst;
9687 };
9688 //%% }
9689
9690 PropertyMapper<SymbolContext::Private> SymbolContext::Private::s_inst;
9691
9692 SymbolContext::SymbolContext(const Definition *def,const Definition *prevDef,const Definition *nextDef)
9693     : RefCountedContext("SymbolContext")
9694 {
9695   p = new Private(def,prevDef,nextDef);
9696 }
9697
9698 SymbolContext::~SymbolContext()
9699 {
9700   delete p;
9701 }
9702
9703 TemplateVariant SymbolContext::get(const char *name) const
9704 {
9705   return p->get(name);
9706 }
9707
9708 //------------------------------------------------------------------------
9709
9710 //%% list SymbolList[Symbol] : list of search symbols with the same name
9711 class SymbolListContext::Private : public GenericNodeListContext
9712 {
9713   public:
9714     Private(const SearchDefinitionList *sdl)
9715     {
9716       QListIterator<Definition> li(*sdl);
9717       Definition *def;
9718       Definition *prev = 0;
9719       for (li.toFirst();(def=li.current());)
9720       {
9721         ++li;
9722         const Definition *next = li.current();
9723         append(SymbolContext::alloc(def,prev,next));
9724         prev = def;
9725       }
9726     }
9727 };
9728
9729 SymbolListContext::SymbolListContext(const SearchDefinitionList *sdl)
9730     : RefCountedContext("SymbolListContext")
9731 {
9732   p = new Private(sdl);
9733 }
9734
9735 SymbolListContext::~SymbolListContext()
9736 {
9737   delete p;
9738 }
9739
9740 // TemplateListIntf
9741 int SymbolListContext::count() const
9742 {
9743   return p->count();
9744 }
9745
9746 TemplateVariant SymbolListContext::at(int index) const
9747 {
9748   return p->at(index);
9749 }
9750
9751 TemplateListIntf::ConstIterator *SymbolListContext::createIterator() const
9752 {
9753   return p->createIterator();
9754 }
9755
9756 //------------------------------------------------------------------------
9757
9758 //%% struct SymbolGroup: search group of similar symbols
9759 //%% {
9760 class SymbolGroupContext::Private
9761 {
9762   public:
9763     Private(const SearchDefinitionList *sdl) : m_sdl(sdl)
9764     {
9765       static bool init=FALSE;
9766       if (!init)
9767       {
9768         s_inst.addProperty("id",     &Private::id);
9769         s_inst.addProperty("name",   &Private::name);
9770         s_inst.addProperty("symbols",&Private::symbolList);
9771         init=TRUE;
9772       }
9773     }
9774     TemplateVariant get(const char *n) const
9775     {
9776       return s_inst.get(this,n);
9777     }
9778     TemplateVariant id() const
9779     {
9780       return m_sdl->id();
9781     }
9782     TemplateVariant name() const
9783     {
9784       return m_sdl->name();
9785     }
9786     TemplateVariant symbolList() const
9787     {
9788       if (!m_cache.symbolList)
9789       {
9790         m_cache.symbolList.reset(SymbolListContext::alloc(m_sdl));
9791       }
9792       return m_cache.symbolList.get();
9793     }
9794   private:
9795     const SearchDefinitionList *m_sdl;
9796     struct Cachable
9797     {
9798       SharedPtr<SymbolListContext> symbolList;
9799     };
9800     mutable Cachable m_cache;
9801     static PropertyMapper<SymbolGroupContext::Private> s_inst;
9802 };
9803 //%% }
9804
9805 PropertyMapper<SymbolGroupContext::Private> SymbolGroupContext::Private::s_inst;
9806
9807 SymbolGroupContext::SymbolGroupContext(const SearchDefinitionList *sdl)
9808     : RefCountedContext("SymbolGroupContext")
9809 {
9810   p = new Private(sdl);
9811 }
9812
9813 SymbolGroupContext::~SymbolGroupContext()
9814 {
9815   delete p;
9816 }
9817
9818 TemplateVariant SymbolGroupContext::get(const char *name) const
9819 {
9820   return p->get(name);
9821 }
9822
9823 //------------------------------------------------------------------------
9824
9825 //%% list SymbolGroupList[SymbolGroup] : list of search groups one per by name
9826 class SymbolGroupListContext::Private : public GenericNodeListContext
9827 {
9828   public:
9829     Private(const SearchIndexList *sil)
9830     {
9831       SDict<SearchDefinitionList>::Iterator li(*sil);
9832       SearchDefinitionList *dl;
9833       for (li.toFirst();(dl=li.current());++li)
9834       {
9835         append(SymbolGroupContext::alloc(dl));
9836       }
9837     }
9838 };
9839
9840 SymbolGroupListContext::SymbolGroupListContext(const SearchIndexList *sil) 
9841     : RefCountedContext("SymbolGroupListContext")
9842 {
9843   p = new Private(sil);
9844 }
9845
9846 SymbolGroupListContext::~SymbolGroupListContext()
9847 {
9848   delete p;
9849 }
9850
9851 // TemplateListIntf
9852 int SymbolGroupListContext::count() const
9853 {
9854   return p->count();
9855 }
9856
9857 TemplateVariant SymbolGroupListContext::at(int index) const
9858 {
9859   return p->at(index);
9860 }
9861
9862 TemplateListIntf::ConstIterator *SymbolGroupListContext::createIterator() const
9863 {
9864   return p->createIterator();
9865 }
9866
9867 //------------------------------------------------------------------------
9868
9869 //%% struct SymbolIndex: search index
9870 //%% {
9871 class SymbolIndexContext::Private
9872 {
9873   public:
9874     Private(const SearchIndexList *sl,const QCString &name) : m_searchList(sl), m_name(name)
9875     {
9876       static bool init=FALSE;
9877       if (!init)
9878       {
9879         s_inst.addProperty("name",        &Private::name);
9880         s_inst.addProperty("letter",      &Private::letter);
9881         s_inst.addProperty("symbolGroups",&Private::symbolGroups);
9882         init=TRUE;
9883       }
9884     }
9885     TemplateVariant get(const char *n) const
9886     {
9887       return s_inst.get(this,n);
9888     }
9889     TemplateVariant name() const
9890     {
9891       return m_name;
9892     }
9893     TemplateVariant letter() const
9894     {
9895       return QString(QChar(m_searchList->letter())).utf8();
9896     }
9897     TemplateVariant symbolGroups() const
9898     {
9899       if (!m_cache.symbolGroups)
9900       {
9901         m_cache.symbolGroups.reset(SymbolGroupListContext::alloc(m_searchList));
9902       }
9903       return m_cache.symbolGroups.get();
9904     }
9905   private:
9906     const SearchIndexList *m_searchList;
9907     QCString m_name;
9908     struct Cachable
9909     {
9910       SharedPtr<SymbolGroupListContext> symbolGroups;
9911     };
9912     mutable Cachable m_cache;
9913     static PropertyMapper<SymbolIndexContext::Private> s_inst;
9914 };
9915 //%% }
9916
9917 PropertyMapper<SymbolIndexContext::Private> SymbolIndexContext::Private::s_inst;
9918
9919 SymbolIndexContext::SymbolIndexContext(const SearchIndexList *sl,const QCString &name)
9920     : RefCountedContext("SymbolIndexContext")
9921 {
9922   p = new Private(sl,name);
9923 }
9924
9925 SymbolIndexContext::~SymbolIndexContext()
9926 {
9927   delete p;
9928 }
9929
9930 TemplateVariant SymbolIndexContext::get(const char *name) const
9931 {
9932   return p->get(name);
9933 }
9934
9935 //------------------------------------------------------------------------
9936
9937 //%% list SymbolIndices[SymbolIndex] : list of search indices one per by type
9938 class SymbolIndicesContext::Private : public GenericNodeListContext
9939 {
9940   public:
9941     Private(const SearchIndexInfo *info)
9942     {
9943       // use info->symbolList to populate the list
9944       SIntDict<SearchIndexList>::Iterator it(info->symbolList);
9945       const SearchIndexList *sl;
9946       for (it.toFirst();(sl=it.current());++it) // for each letter
9947       {
9948         append(SymbolIndexContext::alloc(sl,info->name));
9949       }
9950     }
9951 };
9952
9953 SymbolIndicesContext::SymbolIndicesContext(const SearchIndexInfo *info) : RefCountedContext("SymbolIndicesContext")
9954 {
9955   p = new Private(info);
9956 }
9957
9958 SymbolIndicesContext::~SymbolIndicesContext()
9959 {
9960   delete p;
9961 }
9962
9963 // TemplateListIntf
9964 int SymbolIndicesContext::count() const
9965 {
9966   return p->count();
9967 }
9968
9969 TemplateVariant SymbolIndicesContext::at(int index) const
9970 {
9971   return p->at(index);
9972 }
9973
9974 TemplateListIntf::ConstIterator *SymbolIndicesContext::createIterator() const
9975 {
9976   return p->createIterator();
9977 }
9978
9979 //------------------------------------------------------------------------
9980
9981 //%% struct SearchIndex: search index
9982 //%% {
9983 class SearchIndexContext::Private
9984 {
9985   public:
9986     Private(const SearchIndexInfo *info) : m_info(info)
9987     {
9988       static bool init=FALSE;
9989       if (!init)
9990       {
9991         s_inst.addProperty("name",         &Private::name);
9992         s_inst.addProperty("text",         &Private::text);
9993         s_inst.addProperty("symbolIndices",&Private::symbolIndices);
9994         init=TRUE;
9995       }
9996     }
9997     TemplateVariant get(const char *n) const
9998     {
9999       return s_inst.get(this,n);
10000     }
10001     TemplateVariant name() const
10002     {
10003       return m_info->name;
10004     }
10005     TemplateVariant text() const
10006     {
10007       return m_info->text;
10008     }
10009     TemplateVariant symbolIndices() const
10010     {
10011       if (!m_cache.symbolIndices)
10012       {
10013         m_cache.symbolIndices.reset(SymbolIndicesContext::alloc(m_info));
10014       }
10015       return m_cache.symbolIndices.get();
10016     }
10017   private:
10018     const SearchIndexInfo *m_info;
10019     struct Cachable
10020     {
10021       SharedPtr<SymbolIndicesContext> symbolIndices;
10022     };
10023     mutable Cachable m_cache;
10024     static PropertyMapper<SearchIndexContext::Private> s_inst;
10025 };
10026 //%% }
10027
10028 PropertyMapper<SearchIndexContext::Private> SearchIndexContext::Private::s_inst;
10029
10030 SearchIndexContext::SearchIndexContext(const SearchIndexInfo *info)
10031     : RefCountedContext("SearchIndexContext")
10032 {
10033   p = new Private(info);
10034 }
10035
10036 SearchIndexContext::~SearchIndexContext()
10037 {
10038   delete p;
10039 }
10040
10041 TemplateVariant SearchIndexContext::get(const char *name) const
10042 {
10043   return p->get(name);
10044 }
10045
10046 //------------------------------------------------------------------------
10047
10048 //%% list SearchIndices[SearchIndex] : list of search indices one per by type
10049 class SearchIndicesContext::Private : public GenericNodeListContext
10050 {
10051   public:
10052     Private()
10053     {
10054       const SearchIndexInfo *indices = getSearchIndices();
10055       for (int i=0;i<NUM_SEARCH_INDICES;i++)
10056       {
10057         append(SearchIndexContext::alloc(&indices[i]));
10058       }
10059     }
10060 };
10061
10062 SearchIndicesContext::SearchIndicesContext() : RefCountedContext("SearchIndicesContext")
10063 {
10064   p = new Private;
10065 }
10066
10067 SearchIndicesContext::~SearchIndicesContext()
10068 {
10069   delete p;
10070 }
10071
10072 // TemplateListIntf
10073 int SearchIndicesContext::count() const
10074 {
10075   return p->count();
10076 }
10077
10078 TemplateVariant SearchIndicesContext::at(int index) const
10079 {
10080   return p->at(index);
10081 }
10082
10083 TemplateListIntf::ConstIterator *SearchIndicesContext::createIterator() const
10084 {
10085   return p->createIterator();
10086 }
10087
10088
10089 //------------------------------------------------------------------------
10090
10091 class HtmlEscaper : public TemplateEscapeIntf
10092 {
10093   public:
10094     QCString escape(const QCString &s)
10095     {
10096       return convertToHtml(s,TRUE);
10097     }
10098     void enableTabbing(bool) {}
10099 };
10100
10101 //------------------------------------------------------------------------
10102
10103 class LatexSpaceless : public TemplateSpacelessIntf
10104 {
10105   public:
10106     LatexSpaceless() { reset(); }
10107     void reset() { }
10108     QCString remove(const QCString &s)
10109     {
10110       QGString result;
10111       const char *p = s.data();
10112       char c;
10113       while ((c=*p++))
10114       {
10115         switch(c)
10116         {
10117           case '\t': case ' ': case '\n':
10118             break;
10119           default:
10120             result+=c;
10121             break;
10122         }
10123       }
10124       result+='\0';
10125       return result.data();
10126     }
10127   private:
10128 };
10129
10130 //------------------------------------------------------------------------
10131
10132 class HtmlSpaceless : public TemplateSpacelessIntf
10133 {
10134   public:
10135     HtmlSpaceless() { reset(); }
10136     void reset()
10137     {
10138       m_insideTag = FALSE;
10139       m_insideString = '\0';
10140       m_removeSpaces = TRUE;
10141     }
10142     QCString remove(const QCString &s)
10143     {
10144       QGString result;
10145       const char *p = s.data();
10146       char c;
10147       while ((c=*p++))
10148       {
10149         switch(c)
10150         {
10151           case '<': // start of a tag
10152             if (!m_insideString) m_insideTag=TRUE,m_removeSpaces=FALSE;
10153             result+=c;
10154             break;
10155           case '>': // end of a tag
10156             if (!m_insideString) m_insideTag=FALSE,m_removeSpaces=TRUE;
10157             result+=c;
10158             break;
10159           case '\\': // escaped character in a string
10160             result+=c;
10161             if (m_insideString && *p) result+=*p++;
10162             break;
10163           case '"': case '\'':
10164             if (m_insideTag)
10165             {
10166               if (m_insideString==c) // end of string
10167               {
10168                 m_insideString='\0';
10169               }
10170               else if (m_insideString=='\0') // start of string
10171               {
10172                 m_insideString=c;
10173               }
10174             }
10175             result+=c;
10176             break;
10177           case ' ': case '\t': case '\n': // whitespace
10178             if (!m_insideTag) // outside tags strip consecutive whitespace
10179             {
10180               m_removeSpaces=TRUE;
10181             }
10182             else
10183             {
10184               result+=' ';
10185             }
10186             break;
10187           default:
10188             //if (m_removeSpaces) result+=' ';
10189             result+=c;
10190             m_removeSpaces=FALSE;
10191             break;
10192         }
10193       }
10194       result+='\0';
10195       //printf("HtmlSpaceless::remove({%s})={%s} m_insideTag=%d m_insideString=%c (%d) removeSpaces=%d\n",s.data(),result.data(),
10196       //    m_insideTag,m_insideString,m_insideString,m_removeSpaces);
10197       return result.data();
10198     }
10199   private:
10200     bool m_insideTag;
10201     char m_insideString;
10202     bool m_removeSpaces;
10203 };
10204
10205 //------------------------------------------------------------------------
10206
10207 class LatexEscaper : public TemplateEscapeIntf
10208 {
10209   public:
10210     LatexEscaper() : m_tabbing(FALSE) {}
10211     QCString escape(const QCString &s)
10212     {
10213       return convertToLaTeX(s,m_tabbing);
10214     }
10215     void enableTabbing(bool b) { m_tabbing=b; }
10216   private:
10217     bool m_tabbing;
10218 };
10219
10220
10221 //------------------------------------------------------------------------
10222
10223 #if DEBUG_REF
10224 int RefCountedContext::s_totalCount;
10225 #endif
10226
10227 void generateOutputViaTemplate()
10228 {
10229   msg("Generating output via template engine...\n");
10230   {
10231     TemplateEngine e;
10232     TemplateContext *ctx = e.createContext();
10233     if (ctx)
10234     {
10235       SharedPtr<DoxygenContext>               doxygen              (DoxygenContext::alloc());
10236       SharedPtr<ConfigContext>                config               (ConfigContext::alloc());
10237       SharedPtr<TranslateContext>             tr                   (TranslateContext::alloc());
10238       SharedPtr<ClassListContext>             classList            (ClassListContext::alloc());
10239       SharedPtr<ClassIndexContext>            classIndex           (ClassIndexContext::alloc());
10240       SharedPtr<ClassTreeContext>             classTree            (ClassTreeContext::alloc());
10241       SharedPtr<ClassHierarchyContext>        classHierarchy       (ClassHierarchyContext::alloc());
10242       SharedPtr<NamespaceListContext>         namespaceList        (NamespaceListContext::alloc());
10243       SharedPtr<NamespaceTreeContext>         namespaceTree        (NamespaceTreeContext::alloc());
10244       SharedPtr<DirListContext>               dirList              (DirListContext::alloc());
10245       SharedPtr<FileListContext>              fileList             (FileListContext::alloc());
10246       SharedPtr<FileTreeContext>              fileTree             (FileTreeContext::alloc());
10247       SharedPtr<PageTreeContext>              pageTree             (PageTreeContext::alloc(Doxygen::pageSDict));
10248       SharedPtr<PageListContext>              pageList             (PageListContext::alloc(Doxygen::pageSDict));
10249       SharedPtr<ExampleTreeContext>           exampleTree          (ExampleTreeContext::alloc());
10250       SharedPtr<ExampleListContext>           exampleList          (ExampleListContext::alloc());
10251       SharedPtr<ModuleTreeContext>            moduleTree           (ModuleTreeContext::alloc());
10252       SharedPtr<ModuleListContext>            moduleList           (ModuleListContext::alloc());
10253       SharedPtr<GlobalsIndexContext>          globalsIndex         (GlobalsIndexContext::alloc());
10254       SharedPtr<ClassMembersIndexContext>     classMembersIndex    (ClassMembersIndexContext::alloc());
10255       SharedPtr<NamespaceMembersIndexContext> namespaceMembersIndex(NamespaceMembersIndexContext::alloc());
10256       SharedPtr<SearchIndicesContext>         searchIndices        (SearchIndicesContext::alloc());
10257
10258       //%% Doxygen doxygen:
10259       ctx->set("doxygen",doxygen.get());
10260       //%% Translator tr:
10261       ctx->set("tr",tr.get());
10262       //%% Config config:
10263       ctx->set("config",config.get());
10264       //%% ClassList classList:
10265       ctx->set("classList",classList.get()); // not used for standard HTML
10266       //%% ClassTree classTree:
10267       ctx->set("classTree",classTree.get());
10268       //%% ClassIndex classIndex:
10269       ctx->set("classIndex",classIndex.get());
10270       //%% ClassHierarchy classHierarchy:
10271       ctx->set("classHierarchy",classHierarchy.get());
10272       //%% NamespaceList namespaceList:
10273       ctx->set("namespaceList",namespaceList.get());
10274       //%% NamespaceTree namespaceTree:
10275       ctx->set("namespaceTree",namespaceTree.get());
10276       //%% FileList fileList:
10277       ctx->set("fileList",fileList.get());
10278       //%% FileTree fileTree:
10279       ctx->set("fileTree",fileTree.get());
10280       //%% PageList pageList
10281       ctx->set("pageList",pageList.get());
10282       //%% PageTree pageTree
10283       ctx->set("pageTree",pageTree.get());
10284       //%% ExampleTree exampleTree
10285       ctx->set("exampleTree",exampleTree.get());
10286       //%% ExampleList exampleList
10287       ctx->set("exampleList",exampleList.get());
10288       //%% ModuleTree moduleTree
10289       ctx->set("moduleTree",moduleTree.get());
10290       //%% ModuleList moduleList
10291       ctx->set("moduleList",moduleList.get());
10292       //%% DirList dirList
10293       ctx->set("dirList",dirList.get());
10294       //%% Page mainPage
10295       if (Doxygen::mainPage)
10296       {
10297         SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage,TRUE,FALSE));
10298         ctx->set("mainPage",mainPage.get());
10299       }
10300       else
10301       {
10302         // TODO: for LaTeX output index should be main... => solve in template
10303         Doxygen::mainPage = new PageDef("[generated]",1,"index","",theTranslator->trMainPage());
10304         Doxygen::mainPage->setFileName("index");
10305         SharedPtr<PageContext> mainPage(PageContext::alloc(Doxygen::mainPage,TRUE,FALSE));
10306         ctx->set("mainPage",mainPage.get());
10307       }
10308       //%% GlobalsIndex globalsIndex:
10309       ctx->set("globalsIndex",globalsIndex.get());
10310       //%% ClassMembersIndex classMembersIndex:
10311       ctx->set("classMembersIndex",classMembersIndex.get());
10312       //%% NamespaceMembersIndex namespaceMembersIndex:
10313       ctx->set("namespaceMembersIndex",namespaceMembersIndex.get());
10314       //%% SearchIndicaes searchindicaes
10315       ctx->set("searchIndices",searchIndices.get());
10316       //%% string space
10317       ctx->set("space"," ");
10318
10319       //if (Config_getBool(GENERATE_HTML))
10320       { // render HTML output
10321         e.setTemplateDir("templates/html"); // TODO: make template part user configurable
10322         Template *tpl = e.loadByName("htmllayout.tpl",1);
10323         if (tpl)
10324         {
10325           g_globals.outputFormat = ContextOutputFormat_Html;
10326           g_globals.dynSectionId = 0;
10327           g_globals.outputDir    = Config_getString(HTML_OUTPUT);
10328           QDir dir(g_globals.outputDir);
10329           createSubDirs(dir);
10330           HtmlEscaper htmlEsc;
10331           ctx->setEscapeIntf(Config_getString(HTML_FILE_EXTENSION),&htmlEsc);
10332           HtmlSpaceless spl;
10333           ctx->setSpacelessIntf(&spl);
10334           ctx->setOutputDirectory(g_globals.outputDir);
10335           FTextStream ts;
10336           tpl->render(ts,ctx);
10337           e.unload(tpl);
10338         }
10339       }
10340
10341       // TODO: clean index before each run...
10342
10343       //if (Config_getBool(GENERATE_LATEX))
10344       if (0)
10345       { // render LaTeX output
10346         e.setTemplateDir("templates/latex"); // TODO: make template part user configurable
10347         Template *tpl = e.loadByName("latexlayout.tpl",1);
10348         if (tpl)
10349         {
10350           g_globals.outputFormat = ContextOutputFormat_Latex;
10351           g_globals.dynSectionId = 0;
10352           g_globals.outputDir    = Config_getString(LATEX_OUTPUT);
10353           QDir dir(g_globals.outputDir);
10354           createSubDirs(dir);
10355           LatexEscaper latexEsc;
10356           ctx->setEscapeIntf(".tex",&latexEsc);
10357           LatexSpaceless spl;
10358           ctx->setSpacelessIntf(&spl);
10359           ctx->setOutputDirectory(g_globals.outputDir);
10360           FTextStream ts;
10361           tpl->render(ts,ctx);
10362           e.unload(tpl);
10363         }
10364       }
10365
10366       // clear all cached data in Definition objects.
10367       QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
10368       DefinitionIntf *intf;
10369       for (;(intf=di.current());++di)
10370       {
10371         if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
10372         {
10373           DefinitionListIterator dli(*(DefinitionList*)intf);
10374           Definition *d;
10375           // for each symbol
10376           for (dli.toFirst();(d=dli.current());++dli)
10377           {
10378             d->setCookie(0);
10379           }
10380         }
10381         else // single symbol
10382         {
10383           Definition *d = (Definition *)intf;
10384           d->setCookie(0);
10385         }
10386       }
10387
10388       e.destroyContext(ctx);
10389     }
10390   }
10391 #if DEBUG_REF // should be 0, i.e. all objects are deleted
10392   printf("==== total ref count %d\n",RefCountedContext::s_totalCount);
10393 #endif
10394 }
10395
10396 void generateTemplateFiles(const char *templateDir)
10397 {
10398   if (!templateDir) return;
10399   QDir thisDir;
10400   if (!thisDir.exists(templateDir) && !thisDir.mkdir(templateDir))
10401   {
10402     err("Failed to create output directory '%s'\n",templateDir);
10403     return;
10404   }
10405   QCString outDir = QCString(templateDir)+"/html";
10406   if (!thisDir.exists(outDir) && !thisDir.mkdir(outDir))
10407   {
10408     err("Failed to create output directory '%s'\n",templateDir);
10409     return;
10410   }
10411   ResourceMgr::instance().writeCategory("html",outDir);
10412 }