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