Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / src / classdef.cpp
1 /******************************************************************************
2  *
3  *
4  *
5  * Copyright (C) 1997-2014 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby
9  * granted. No representations are made about the suitability of this software
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #include <stdio.h>
19 #include <qfile.h>
20 #include <qregexp.h>
21 #include "classdef.h"
22 #include "classlist.h"
23 #include "entry.h"
24 #include "doxygen.h"
25 #include "membername.h"
26 #include "message.h"
27 #include "config.h"
28 #include "util.h"
29 #include "diagram.h"
30 #include "language.h"
31 #include "htmlhelp.h"
32 #include "example.h"
33 #include "outputlist.h"
34 #include "dot.h"
35 #include "defargs.h"
36 #include "debug.h"
37 #include "docparser.h"
38 #include "searchindex.h"
39 #include "vhdldocgen.h"
40 #include "layout.h"
41 #include "arguments.h"
42 #include "memberlist.h"
43 #include "groupdef.h"
44 #include "filedef.h"
45 #include "namespacedef.h"
46 #include "membergroup.h"
47
48 //-----------------------------------------------------------------------------
49
50 /** Private data associated with a ClassDef object. */
51 class ClassDefImpl
52 {
53   public:
54     ClassDefImpl();
55    ~ClassDefImpl();
56     void init(const char *defFileName, const char *name,
57               const QCString &ctStr, const char *fName);
58
59     /*! file name that forms the base for the output file containing the
60      *  class documentation. For compatibility with Qt (e.g. links via tag
61      *  files) this name cannot be derived from the class name directly.
62      */
63     QCString fileName;
64
65     /*! Include information about the header file should be included
66      *  in the documentation. 0 by default, set by setIncludeFile().
67      */
68     IncludeInfo *incInfo;
69
70     /*! List of base class (or super-classes) from which this class derives
71      *  directly.
72      */
73     BaseClassList *inherits;
74
75     /*! List of sub-classes that directly derive from this class
76      */
77     BaseClassList *inheritedBy;
78
79     /*! Namespace this class is part of
80      *  (this is the inner most namespace in case of nested namespaces)
81      */
82     NamespaceDef  *nspace;
83
84     /*! File this class is defined in */
85     FileDef *fileDef;
86
87     /*! List of all members (including inherited members) */
88     MemberNameInfoSDict *allMemberNameInfoSDict;
89
90     /*! Template arguments of this class */
91     ArgumentList *tempArgs;
92
93     /*! Type constraints for template parameters */
94     ArgumentList *typeConstraints;
95
96     /*! Files that were used for generating the class documentation. */
97     FileList files;
98
99     /*! Examples that use this class */
100     ExampleSDict *exampleSDict;
101
102     /*! Holds the kind of "class" this is. */
103     ClassDef::CompoundType compType;
104
105     /*! The protection level in which this class was found.
106      *  Typically Public, but for nested classes this can also be Protected
107      *  or Private.
108      */
109     Protection prot;
110
111     /*! The inner classes contained in this class. Will be 0 if there are
112      *  no inner classes.
113      */
114     ClassSDict *innerClasses;
115
116     /* classes for the collaboration diagram */
117     UsesClassDict *usesImplClassDict;
118     UsesClassDict *usedByImplClassDict;
119     UsesClassDict *usesIntfClassDict;
120
121     /*! Template instances that exists of this class, the key in the
122      *  dictionary is the template argument list.
123      */
124     QDict<ClassDef> *templateInstances;
125
126     /*! Template instances that exists of this class, as defined by variables.
127      *  We do NOT want to document these individually. The key in the
128      *  dictionary is the template argument list.
129      */
130     QDict<ClassDef> *variableInstances;
131
132     QDict<int> *templBaseClassNames;
133
134     /*! The class this class is an instance of. */
135     ClassDef *templateMaster;
136
137     /*! local class name which could be a typedef'ed alias name. */
138     QCString className;
139
140     /*! If this class is a Objective-C category, then this points to the
141      *  class which is extended.
142      */
143     ClassDef *categoryOf;
144
145     QList<MemberList> memberLists;
146
147     /* user defined member groups */
148     MemberGroupSDict *memberGroupSDict;
149
150     /*! Is this an abstact class? */
151     bool isAbstract;
152
153     /*! Is the class part of an unnamed namespace? */
154     bool isStatic;
155
156     /*! TRUE if classes members are merged with those of the base classes. */
157     bool membersMerged;
158
159     /*! TRUE if the class is defined in a source file rather than a header file. */
160     bool isLocal;
161
162     bool isTemplArg;
163
164     /*! Does this class group its user-grouped members
165      *  as a sub-section of the normal (public/protected/..)
166      *  groups?
167      */
168     bool subGrouping;
169
170     /** Reason of existence is a "use" relation */
171     bool usedOnly;
172
173     /** List of titles to use for the summary */
174     SDict<QCString> vhdlSummaryTitles;
175
176     /** Is this a simple (non-nested) C structure? */
177     bool isSimple;
178
179     /** Does this class overloaded the -> operator? */
180     MemberDef *arrowOperator;
181
182     ClassList *taggedInnerClasses;
183     ClassDef *tagLessRef;
184
185     /** Does this class represent a Java style enum? */
186     bool isJavaEnum;
187
188     bool isGeneric;
189
190     bool isAnonymous;
191
192     uint64 spec;
193 };
194
195 void ClassDefImpl::init(const char *defFileName, const char *name,
196                         const QCString &ctStr, const char *fName)
197 {
198   if (fName)
199   {
200     fileName=stripExtension(fName);
201   }
202   else
203   {
204     fileName=ctStr+name;
205   }
206   exampleSDict = 0;
207   inherits    = 0;
208   inheritedBy = 0;
209   allMemberNameInfoSDict = 0;
210   incInfo=0;
211   tempArgs=0;
212   typeConstraints=0;
213   prot=Public;
214   nspace=0;
215   fileDef=0;
216   usesImplClassDict=0;
217   usedByImplClassDict=0;
218   usesIntfClassDict=0;
219   memberGroupSDict = 0;
220   innerClasses = 0;
221   subGrouping=Config_getBool("SUBGROUPING");
222   templateInstances = 0;
223   variableInstances = 0;
224   templateMaster =0;
225   templBaseClassNames = 0;
226   isAbstract = FALSE;
227   isStatic = FALSE;
228   isTemplArg = FALSE;
229   membersMerged = FALSE;
230   categoryOf = 0;
231   usedOnly = FALSE;
232   isSimple = Config_getBool("INLINE_SIMPLE_STRUCTS");
233   arrowOperator = 0;
234   taggedInnerClasses = 0;
235   tagLessRef = 0;
236   spec=0;
237   //QCString ns;
238   //extractNamespaceName(name,className,ns);
239   //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data());
240
241   // we cannot use getLanguage at this point, as setLanguage has not been called.
242   SrcLangExt lang = getLanguageFromFileName(defFileName);
243   if ((lang==SrcLangExt_Cpp || lang==SrcLangExt_ObjC) &&
244       guessSection(defFileName)==Entry::SOURCE_SEC)
245   {
246     isLocal=TRUE;
247   }
248   else
249   {
250     isLocal=FALSE;
251   }
252   isGeneric = (lang==SrcLangExt_CSharp || lang==SrcLangExt_Java) && QCString(name).find('<')!=-1;
253   isAnonymous = QCString(name).find('@')!=-1;
254 }
255
256 ClassDefImpl::ClassDefImpl() : vhdlSummaryTitles(17)
257 {
258   vhdlSummaryTitles.setAutoDelete(TRUE);
259 }
260
261 ClassDefImpl::~ClassDefImpl()
262 {
263   delete inherits;
264   delete inheritedBy;
265   delete allMemberNameInfoSDict;
266   delete exampleSDict;
267   delete usesImplClassDict;
268   delete usedByImplClassDict;
269   delete usesIntfClassDict;
270   delete incInfo;
271   delete memberGroupSDict;
272   delete innerClasses;
273   delete templateInstances;
274   delete variableInstances;
275   delete templBaseClassNames;
276   delete tempArgs;
277   delete typeConstraints;
278   delete taggedInnerClasses;
279 }
280
281 // constructs a new class definition
282 ClassDef::ClassDef(
283     const char *defFileName,int defLine,int defColumn,
284     const char *nm,CompoundType ct,
285     const char *lref,const char *fName,
286     bool isSymbol,bool isJavaEnum)
287  : Definition(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol)
288 {
289   visited=FALSE;
290   setReference(lref);
291   m_impl = new ClassDefImpl;
292   m_impl->compType = ct;
293   m_impl->isJavaEnum = isJavaEnum;
294   m_impl->init(defFileName,name(),compoundTypeString(),fName);
295 }
296
297 // destroy the class definition
298 ClassDef::~ClassDef()
299 {
300   delete m_impl;
301 }
302
303 QCString ClassDef::getMemberListFileName() const
304 {
305   return convertNameToFile(compoundTypeString()+name()+"-members");
306 }
307
308 QCString ClassDef::displayName(bool includeScope) const
309 {
310   //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
311   SrcLangExt lang = getLanguage();
312   //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
313   QCString n;
314   if (lang==SrcLangExt_VHDL)
315   {
316     n = VhdlDocGen::getClassName(this);
317   }
318   else
319   {
320     if (includeScope)
321     {
322       n=qualifiedNameWithTemplateParameters();
323     }
324     else
325     {
326       n=className();
327     }
328   }
329   QCString sep=getLanguageSpecificSeparator(lang);
330   if (sep!="::")
331   {
332     n=substitute(n,"::",sep);
333   }
334   if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p")
335   {
336     n="<"+n.left(n.length()-2)+">";
337   }
338   //else if (n.right(2)=="-g")
339   //{
340   //  n = n.left(n.length()-2);
341   //}
342   //printf("ClassDef::displayName()=%s\n",n.data());
343   if (n.find('@')!=-1)
344   {
345     return removeAnonymousScopes(n);
346   }
347   else
348   {
349     return n;
350   }
351 }
352
353 // inserts a base/super class in the inheritance list
354 void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p,
355                                Specifier s,const char *t)
356 {
357   //printf("*** insert base class %s into %s\n",cd->name().data(),name().data());
358   //inherits->inSort(new BaseClassDef(cd,p,s,t));
359   if (m_impl->inherits==0)
360   {
361     m_impl->inherits = new BaseClassList;
362     m_impl->inherits->setAutoDelete(TRUE);
363   }
364   m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t));
365   m_impl->isSimple = FALSE;
366 }
367
368 // inserts a derived/sub class in the inherited-by list
369 void ClassDef::insertSubClass(ClassDef *cd,Protection p,
370                                 Specifier s,const char *t)
371 {
372   //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data());
373   static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
374   if (!extractPrivate && cd->protection()==Private) return;
375   if (m_impl->inheritedBy==0)
376   {
377     m_impl->inheritedBy   = new BaseClassList;
378     m_impl->inheritedBy->setAutoDelete(TRUE);
379   }
380   m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t));
381   m_impl->isSimple = FALSE;
382 }
383
384 void ClassDef::addMembersToMemberGroup()
385 {
386   QListIterator<MemberList> mli(m_impl->memberLists);
387   MemberList *ml;
388   for (mli.toFirst();(ml=mli.current());++mli)
389   {
390     if ((ml->listType()&MemberListType_detailedLists)==0)
391     {
392       ::addMembersToMemberGroup(ml,&m_impl->memberGroupSDict,this);
393     }
394   }
395
396   // add members inside sections to their groups
397   if (m_impl->memberGroupSDict)
398   {
399     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
400     MemberGroup *mg;
401     for (;(mg=mgli.current());++mgli)
402     {
403       if (mg->allMembersInSameSection() && m_impl->subGrouping)
404       {
405         //printf("addToDeclarationSection(%s)\n",mg->header().data());
406         mg->addToDeclarationSection();
407       }
408     }
409   }
410 }
411
412 // adds new member definition to the class
413 void ClassDef::internalInsertMember(MemberDef *md,
414                                     Protection prot,
415                                     bool addToAllList
416                                    )
417 {
418   //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden());
419   if (md->isHidden()) return;
420
421   if (getLanguage()==SrcLangExt_VHDL)
422   {
423     QCString title=VhdlDocGen::trVhdlType(md->getMemberSpecifiers(),FALSE);
424     if (!m_impl->vhdlSummaryTitles.find(title))
425     {
426       m_impl->vhdlSummaryTitles.append(title,new QCString(title));
427     }
428   }
429
430   if (1 /*!isReference()*/) // changed to 1 for showing members of external
431                             // classes when HAVE_DOT and UML_LOOK are enabled.
432   {
433     bool isSimple=FALSE;
434
435     /********************************************/
436     /* insert member in the declaration section */
437     /********************************************/
438     if (md->isRelated() && protectionLevelVisible(prot))
439     {
440       addMemberToList(MemberListType_related,md,TRUE);
441     }
442     else if (md->isFriend())
443     {
444       addMemberToList(MemberListType_friends,md,TRUE);
445     }
446     else
447     {
448       switch (md->memberType())
449       {
450         case MemberType_Service: // UNO IDL
451           addMemberToList(MemberListType_services,md,TRUE);
452           break;
453         case MemberType_Interface: // UNO IDL
454           addMemberToList(MemberListType_interfaces,md,TRUE);
455           break;
456         case MemberType_Signal: // Qt specific
457           addMemberToList(MemberListType_signals,md,TRUE);
458           break;
459         case MemberType_DCOP:   // KDE2 specific
460           addMemberToList(MemberListType_dcopMethods,md,TRUE);
461           break;
462         case MemberType_Property:
463           addMemberToList(MemberListType_properties,md,TRUE);
464           break;
465         case MemberType_Event:
466           addMemberToList(MemberListType_events,md,TRUE);
467           break;
468         case MemberType_Slot:   // Qt specific
469           switch (prot)
470           {
471             case Protected:
472             case Package: // slots in packages are not possible!
473               addMemberToList(MemberListType_proSlots,md,TRUE);
474               break;
475             case Public:
476               addMemberToList(MemberListType_pubSlots,md,TRUE);
477               break;
478             case Private:
479               addMemberToList(MemberListType_priSlots,md,TRUE);
480               break;
481           }
482           break;
483         default: // any of the other members
484           if (md->isStatic())
485           {
486             if (md->isVariable())
487             {
488               switch (prot)
489               {
490                 case Protected:
491                   addMemberToList(MemberListType_proStaticAttribs,md,TRUE);
492                   break;
493                 case Package:
494                   addMemberToList(MemberListType_pacStaticAttribs,md,TRUE);
495                   break;
496                 case Public:
497                   addMemberToList(MemberListType_pubStaticAttribs,md,TRUE);
498                   break;
499                 case Private:
500                   addMemberToList(MemberListType_priStaticAttribs,md,TRUE);
501                   break;
502               }
503             }
504             else // function
505             {
506               switch (prot)
507               {
508                 case Protected:
509                   addMemberToList(MemberListType_proStaticMethods,md,TRUE);
510                   break;
511                 case Package:
512                   addMemberToList(MemberListType_pacStaticMethods,md,TRUE);
513                   break;
514                 case Public:
515                   addMemberToList(MemberListType_pubStaticMethods,md,TRUE);
516                   break;
517                 case Private:
518                   addMemberToList(MemberListType_priStaticMethods,md,TRUE);
519                   break;
520               }
521             }
522           }
523           else // not static
524           {
525             if (md->isVariable())
526             {
527               switch (prot)
528               {
529                 case Protected:
530                   addMemberToList(MemberListType_proAttribs,md,TRUE);
531                   break;
532                 case Package:
533                   addMemberToList(MemberListType_pacAttribs,md,TRUE);
534                   break;
535                 case Public:
536                   addMemberToList(MemberListType_pubAttribs,md,TRUE);
537                   isSimple=!md->isFunctionPtr();
538                   break;
539                 case Private:
540                   addMemberToList(MemberListType_priAttribs,md,TRUE);
541                   break;
542               }
543             }
544             else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue())
545             {
546               switch (prot)
547               {
548                 case Protected:
549                   addMemberToList(MemberListType_proTypes,md,TRUE);
550                   break;
551                 case Package:
552                   addMemberToList(MemberListType_pacTypes,md,TRUE);
553                   break;
554                 case Public:
555                   addMemberToList(MemberListType_pubTypes,md,TRUE);
556                   isSimple=QCString(md->typeString()).find(")(")==-1;
557                   break;
558                 case Private:
559                   addMemberToList(MemberListType_priTypes,md,TRUE);
560                   break;
561               }
562             }
563             else // member function
564             {
565               switch (prot)
566               {
567                 case Protected:
568                   addMemberToList(MemberListType_proMethods,md,TRUE);
569                   break;
570                 case Package:
571                   addMemberToList(MemberListType_pacMethods,md,TRUE);
572                   break;
573                 case Public:
574                   addMemberToList(MemberListType_pubMethods,md,TRUE);
575                   break;
576                 case Private:
577                   addMemberToList(MemberListType_priMethods,md,TRUE);
578                   break;
579               }
580             }
581           }
582           break;
583       }
584     }
585     if (!isSimple) // not a simple field -> not a simple struct
586     {
587       m_impl->isSimple = FALSE;
588     }
589     //printf("adding %s simple=%d total_simple=%d\n",name().data(),isSimple,m_impl->isSimple);
590
591     /*******************************************************/
592     /* insert member in the detailed documentation section */
593     /*******************************************************/
594     if ((md->isRelated() && protectionLevelVisible(prot)) || md->isFriend())
595     {
596       addMemberToList(MemberListType_relatedMembers,md,FALSE);
597     }
598     else
599     {
600       switch (md->memberType())
601       {
602         case MemberType_Service: // UNO IDL
603           addMemberToList(MemberListType_serviceMembers,md,FALSE);
604           break;
605         case MemberType_Interface: // UNO IDL
606           addMemberToList(MemberListType_interfaceMembers,md,FALSE);
607           break;
608         case MemberType_Property:
609           addMemberToList(MemberListType_propertyMembers,md,FALSE);
610           break;
611         case MemberType_Event:
612           addMemberToList(MemberListType_eventMembers,md,FALSE);
613           break;
614         case MemberType_Signal: // fall through
615         case MemberType_DCOP:
616           addMemberToList(MemberListType_functionMembers,md,FALSE);
617           break;
618         case MemberType_Slot:
619           if (protectionLevelVisible(prot))
620           {
621             addMemberToList(MemberListType_functionMembers,md,FALSE);
622           }
623           break;
624         default: // any of the other members
625           if (protectionLevelVisible(prot))
626           {
627             switch (md->memberType())
628             {
629               case MemberType_Typedef:
630                 addMemberToList(MemberListType_typedefMembers,md,FALSE);
631                 break;
632               case MemberType_Enumeration:
633                 addMemberToList(MemberListType_enumMembers,md,FALSE);
634                 break;
635               case MemberType_EnumValue:
636                 addMemberToList(MemberListType_enumValMembers,md,FALSE);
637                 break;
638               case MemberType_Function:
639                 if (md->isConstructor() || md->isDestructor())
640                 {
641                   MemberList *ml = createMemberList(MemberListType_constructors);
642                   ml->append(md);
643                 }
644                 else
645                 {
646                   addMemberToList(MemberListType_functionMembers,md,FALSE);
647                 }
648                 break;
649               case MemberType_Variable:
650                 addMemberToList(MemberListType_variableMembers,md,FALSE);
651                 break;
652               default:
653                 err("Unexpected member type %d found!\n",md->memberType());
654             }
655           }
656           break;
657       }
658     }
659
660     /*************************************************/
661     /* insert member in the appropriate member group */
662     /*************************************************/
663     // Note: this must be done AFTER inserting the member in the
664     // regular groups
665     //addMemberToGroup(md,groupId);
666
667   }
668
669   if (md->virtualness()==Pure)
670   {
671     m_impl->isAbstract=TRUE;
672   }
673
674   if (md->name()=="operator->")
675   {
676     m_impl->arrowOperator=md;
677   }
678
679   //::addClassMemberNameToIndex(md);
680   if (addToAllList &&
681       !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
682         md->isFriend() &&
683         (QCString(md->typeString())=="friend class" ||
684          QCString(md->typeString())=="friend struct" ||
685          QCString(md->typeString())=="friend union")))
686   {
687     //printf("=======> adding member %s to class %s\n",md->name().data(),name().data());
688     MemberInfo *mi = new MemberInfo((MemberDef *)md,
689                                      prot,md->virtualness(),FALSE);
690     MemberNameInfo *mni=0;
691     if (m_impl->allMemberNameInfoSDict==0)
692     {
693       m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
694       m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
695     }
696     if ((mni=m_impl->allMemberNameInfoSDict->find(md->name())))
697     {
698       mni->append(mi);
699     }
700     else
701     {
702       mni = new MemberNameInfo(md->name());
703       mni->append(mi);
704       m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni);
705     }
706   }
707 }
708
709 void ClassDef::insertMember(MemberDef *md)
710 {
711   internalInsertMember(md,md->protection(),TRUE);
712 }
713
714 // compute the anchors for all members
715 void ClassDef::computeAnchors()
716 {
717   //ClassDef *context = Config_getBool("INLINE_INHERITED_MEMB") ? this : 0;
718   //const char *letters = "abcdefghijklmnopqrstuvwxyz0123456789";
719   QListIterator<MemberList> mli(m_impl->memberLists);
720   MemberList *ml;
721   //int index = 0;
722   for (mli.toFirst();(ml=mli.current());++mli)
723   {
724     if ((ml->listType()&MemberListType_detailedLists)==0)
725     {
726       setAnchors(ml);
727     }
728   }
729
730   if (m_impl->memberGroupSDict)
731   {
732     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
733     MemberGroup *mg;
734     for (;(mg=mgli.current());++mgli)
735     {
736       mg->setAnchors();
737     }
738   }
739 }
740
741 void ClassDef::distributeMemberGroupDocumentation()
742 {
743   if (m_impl->memberGroupSDict)
744   {
745     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
746     MemberGroup *mg;
747     for (;(mg=mgli.current());++mgli)
748     {
749       mg->distributeMemberGroupDocumentation();
750     }
751   }
752 }
753
754 void ClassDef::findSectionsInDocumentation()
755 {
756   docFindSections(documentation(),this,0,docFile());
757   if (m_impl->memberGroupSDict)
758   {
759     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
760     MemberGroup *mg;
761     for (;(mg=mgli.current());++mgli)
762     {
763       mg->findSectionsInDocumentation();
764     }
765   }
766   QListIterator<MemberList> mli(m_impl->memberLists);
767   MemberList *ml;
768   for (mli.toFirst();(ml=mli.current());++mli)
769   {
770     if ((ml->listType()&MemberListType_detailedLists)==0)
771     {
772       ml->findSectionsInDocumentation();
773     }
774   }
775 }
776
777
778 // add a file name to the used files set
779 void ClassDef::insertUsedFile(FileDef *fd)
780 {
781   if (fd==0) return;
782   if (m_impl->files.find(fd)==-1) m_impl->files.append(fd);
783   if (m_impl->templateInstances)
784   {
785     QDictIterator<ClassDef> qdi(*m_impl->templateInstances);
786     ClassDef *cd;
787     for (qdi.toFirst();(cd=qdi.current());++qdi)
788     {
789       cd->insertUsedFile(fd);
790     }
791   }
792 }
793
794 static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd)
795 {
796   if (bcd->prot!=Public || bcd->virt!=Normal)
797   {
798     ol.startTypewriter();
799     ol.docify(" [");
800     QStrList sl;
801     if      (bcd->prot==Protected) sl.append("protected");
802     else if (bcd->prot==Private)   sl.append("private");
803     if      (bcd->virt==Virtual)   sl.append("virtual");
804     const char *s=sl.first();
805     while (s)
806     {
807       ol.docify(s);
808       s=sl.next();
809       if (s) ol.docify(", ");
810     }
811     ol.docify("]");
812     ol.endTypewriter();
813   }
814 }
815
816 void ClassDef::setIncludeFile(FileDef *fd,
817              const char *includeName,bool local, bool force)
818 {
819   //printf("ClassDef::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force);
820   if (!m_impl->incInfo) m_impl->incInfo=new IncludeInfo;
821   if ((includeName && m_impl->incInfo->includeName.isEmpty()) ||
822       (fd!=0 && m_impl->incInfo->fileDef==0)
823      )
824   {
825     //printf("Setting file info\n");
826     m_impl->incInfo->fileDef     = fd;
827     m_impl->incInfo->includeName = includeName;
828     m_impl->incInfo->local       = local;
829   }
830   if (force && includeName)
831   {
832     m_impl->incInfo->includeName = includeName;
833     m_impl->incInfo->local       = local;
834   }
835 }
836
837 // TODO: fix this: a nested template class can have multiple outer templates
838 //ArgumentList *ClassDef::outerTemplateArguments() const
839 //{
840 //  int ti;
841 //  ClassDef *pcd=0;
842 //  int pi=0;
843 //  if (m_impl->tempArgs) return m_impl->tempArgs;
844 //  // find the outer most class scope
845 //  while ((ti=name().find("::",pi))!=-1 &&
846 //      (pcd=getClass(name().left(ti)))==0
847 //        ) pi=ti+2;
848 //  if (pcd)
849 //  {
850 //    return pcd->templateArguments();
851 //  }
852 //  return 0;
853 //}
854
855 static void searchTemplateSpecs(/*in*/  Definition *d,
856                                 /*out*/ QList<ArgumentList> &result,
857                                 /*out*/ QCString &name)
858 {
859   if (d->definitionType()==Definition::TypeClass)
860   {
861     if (d->getOuterScope())
862     {
863       searchTemplateSpecs(d->getOuterScope(),result,name);
864     }
865     ClassDef *cd=(ClassDef *)d;
866     if (!name.isEmpty()) name+="::";
867     QCString clName = d->localName();
868     if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p")
869     {
870       clName = clName.left(clName.length()-2);
871     }
872     name+=clName;
873     bool isSpecialization = d->localName().find('<')!=-1;
874     if (cd->templateArguments())
875     {
876       result.append(cd->templateArguments());
877       if (!isSpecialization)
878       {
879         name+=tempArgListToString(cd->templateArguments());
880       }
881     }
882   }
883   else
884   {
885     name+=d->qualifiedName();
886   }
887 }
888
889 static void writeTemplateSpec(OutputList &ol,Definition *d,
890             const QCString &type)
891 {
892   QList<ArgumentList> specs;
893   QCString name;
894   searchTemplateSpecs(d,specs,name);
895   if (specs.count()>0) // class has template scope specifiers
896   {
897     ol.startSubsubsection();
898     QListIterator<ArgumentList> spi(specs);
899     ArgumentList *al;
900     for (spi.toFirst();(al=spi.current());++spi)
901     {
902       ol.docify("template<");
903       QListIterator<Argument> ali(*al);
904       Argument *a;
905       while ((a=ali.current()))
906       {
907         ol.docify(a->type);
908         if (!a->name.isEmpty())
909         {
910           ol.docify(" ");
911           ol.docify(a->name);
912         }
913         if (a->defval.length()!=0)
914         {
915           ol.docify(" = ");
916           ol.docify(a->defval);
917         }
918         ++ali;
919         a=ali.current();
920         if (a) ol.docify(", ");
921       }
922       ol.docify(">");
923       ol.pushGeneratorState();
924       ol.disableAllBut(OutputGenerator::Html);
925       ol.lineBreak();
926       ol.popGeneratorState();
927     }
928     ol.docify(type.lower()+" "+name);
929     ol.endSubsubsection();
930     ol.writeString("\n");
931   }
932 }
933
934 void ClassDef::writeBriefDescription(OutputList &ol,bool exampleFlag)
935 {
936   if (hasBriefDescription())
937   {
938     ol.startParagraph();
939     ol.generateDoc(briefFile(),briefLine(),this,0,
940                    briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
941     ol.pushGeneratorState();
942     ol.disable(OutputGenerator::RTF);
943     ol.writeString(" \n");
944     ol.enable(OutputGenerator::RTF);
945     ol.popGeneratorState();
946
947     if (hasDetailedDescription() || exampleFlag)
948     {
949       writeMoreLink(ol,anchor());
950     }
951
952     ol.endParagraph();
953   }
954   ol.writeSynopsis();
955 }
956
957 void ClassDef::writeDetailedDocumentationBody(OutputList &ol)
958 {
959   static bool repeatBrief = Config_getBool("REPEAT_BRIEF");
960
961   ol.startTextBlock();
962
963   if (getLanguage()==SrcLangExt_Cpp)
964   {
965     writeTemplateSpec(ol,this,compoundTypeString());
966   }
967
968   // repeat brief description
969   if (!briefDescription().isEmpty() && repeatBrief)
970   {
971     ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
972   }
973   if (!briefDescription().isEmpty() && repeatBrief &&
974       !documentation().isEmpty())
975   {
976     ol.pushGeneratorState();
977     ol.disable(OutputGenerator::Html);
978     ol.writeString("\n\n");
979     ol.popGeneratorState();
980   }
981   // write documentation
982   if (!documentation().isEmpty())
983   {
984     ol.generateDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE);
985   }
986   // write type constraints
987   writeTypeConstraints(ol,this,m_impl->typeConstraints);
988
989   // write examples
990   if (hasExamples() && m_impl->exampleSDict)
991   {
992     ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
993     ol.startDescForItem();
994     //ol.startParagraph();
995     writeExample(ol,m_impl->exampleSDict);
996     //ol.endParagraph();
997     ol.endDescForItem();
998     ol.endSimpleSect();
999   }
1000   //ol.newParagraph();
1001   writeSourceDef(ol,name());
1002   ol.endTextBlock();
1003 }
1004
1005 bool ClassDef::hasDetailedDescription() const
1006 {
1007   static bool repeatBrief = Config_getBool("REPEAT_BRIEF");
1008   static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
1009   return ((!briefDescription().isEmpty() && repeatBrief) ||
1010           !documentation().isEmpty() ||
1011           (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef()));
1012 }
1013
1014 // write the detailed description for this class
1015 void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &/*pageType*/, bool exampleFlag,
1016                                         const QCString &title,const QCString &anchor)
1017 {
1018   if (hasDetailedDescription() || exampleFlag)
1019   {
1020     ol.pushGeneratorState();
1021       ol.disable(OutputGenerator::Html);
1022       ol.writeRuler();
1023     ol.popGeneratorState();
1024
1025     ol.pushGeneratorState();
1026       ol.disableAllBut(OutputGenerator::Html);
1027       ol.writeAnchor(0,anchor.isEmpty() ? QCString("details") : anchor);
1028     ol.popGeneratorState();
1029
1030     if (!anchor.isEmpty())
1031     {
1032       ol.pushGeneratorState();
1033       ol.disable(OutputGenerator::Html);
1034       ol.disable(OutputGenerator::Man);
1035       ol.writeAnchor(getOutputFileBase(),anchor);
1036       ol.popGeneratorState();
1037     }
1038
1039     ol.startGroupHeader();
1040     ol.parseText(title);
1041     ol.endGroupHeader();
1042
1043     writeDetailedDocumentationBody(ol);
1044   }
1045   else
1046   {
1047     //writeTemplateSpec(ol,this,pageType);
1048   }
1049 }
1050
1051 QCString ClassDef::generatedFromFiles() const
1052 {
1053   QCString result;
1054   SrcLangExt lang = getLanguage();
1055   if (lang==SrcLangExt_Fortran)
1056   {
1057     result = theTranslator->trGeneratedFromFilesFortran(
1058           getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType,
1059           m_impl->files.count()==1);
1060   }
1061   else if (isJavaEnum())
1062   {
1063     result = theTranslator->trEnumGeneratedFromFiles(m_impl->files.count()==1);
1064   }
1065   else if (m_impl->compType==Service)
1066   {
1067     result = theTranslator->trServiceGeneratedFromFiles(m_impl->files.count()==1);
1068   }
1069   else if (m_impl->compType==Singleton)
1070   {
1071     result = theTranslator->trSingletonGeneratedFromFiles(m_impl->files.count()==1);
1072   }
1073   else
1074   {
1075     result = theTranslator->trGeneratedFromFiles(
1076           getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType,
1077           m_impl->files.count()==1);
1078   }
1079   return result;
1080 }
1081
1082 void ClassDef::showUsedFiles(OutputList &ol)
1083 {
1084   ol.pushGeneratorState();
1085   ol.disable(OutputGenerator::Man);
1086
1087
1088   ol.writeRuler();
1089   ol.parseText(generatedFromFiles());
1090
1091   bool first=TRUE;
1092   QListIterator<FileDef> li(m_impl->files);
1093   FileDef *fd;
1094   for (;(fd=li.current());++li)
1095   {
1096     if (first)
1097     {
1098       first=FALSE;
1099       ol.startItemList();
1100     }
1101
1102     ol.startItemListItem();
1103     QCString path=fd->getPath();
1104     if (Config_getBool("FULL_PATH_NAMES"))
1105     {
1106       ol.docify(stripFromPath(path));
1107     }
1108
1109     QCString fname = fd->name();
1110     if (!fd->getVersion().isEmpty()) // append version if available
1111     {
1112       fname += " (" + fd->getVersion() + ")";
1113     }
1114
1115     // for HTML
1116     ol.pushGeneratorState();
1117     ol.disableAllBut(OutputGenerator::Html);
1118     if (fd->generateSourceFile())
1119     {
1120       ol.writeObjectLink(0,fd->getSourceFileBase(),0,fname);
1121     }
1122     else if (fd->isLinkable())
1123     {
1124       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
1125           fname);
1126     }
1127     else
1128     {
1129       ol.docify(fname);
1130     }
1131     ol.popGeneratorState();
1132
1133     // for other output formats
1134     ol.pushGeneratorState();
1135     ol.disable(OutputGenerator::Html);
1136     if (fd->isLinkable())
1137     {
1138       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
1139           fname);
1140     }
1141     else
1142     {
1143       ol.docify(fname);
1144     }
1145     ol.popGeneratorState();
1146
1147     ol.endItemListItem();
1148   }
1149   if (!first) ol.endItemList();
1150
1151   ol.popGeneratorState();
1152 }
1153
1154 int ClassDef::countInheritanceNodes()
1155 {
1156   int count=0;
1157   BaseClassDef *ibcd;
1158   if (m_impl->inheritedBy)
1159   {
1160     BaseClassListIterator it(*m_impl->inheritedBy);
1161     for (;(ibcd=it.current());++it)
1162     {
1163       ClassDef *icd=ibcd->classDef;
1164       if ( icd->isVisibleInHierarchy()) count++;
1165     }
1166   }
1167   if (m_impl->inherits)
1168   {
1169     BaseClassListIterator it(*m_impl->inherits);
1170     for (;(ibcd=it.current());++it)
1171     {
1172       ClassDef *icd=ibcd->classDef;
1173       if ( icd->isVisibleInHierarchy()) count++;
1174     }
1175   }
1176   return count;
1177 }
1178
1179 void ClassDef::writeInheritanceGraph(OutputList &ol)
1180 {
1181   // count direct inheritance relations
1182   int count=countInheritanceNodes();
1183
1184   bool renderDiagram = FALSE;
1185   if (Config_getBool("HAVE_DOT") &&
1186       (Config_getBool("CLASS_DIAGRAMS") || Config_getBool("CLASS_GRAPH")))
1187     // write class diagram using dot
1188   {
1189     DotClassGraph inheritanceGraph(this,DotNode::Inheritance);
1190     if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig())
1191     {
1192       ol.pushGeneratorState();
1193       ol.disable(OutputGenerator::Man);
1194       ol.startDotGraph();
1195       ol.parseText(theTranslator->trClassDiagram(displayName()));
1196       ol.endDotGraph(inheritanceGraph);
1197       ol.popGeneratorState();
1198       renderDiagram = TRUE;
1199     }
1200   }
1201   else if (Config_getBool("CLASS_DIAGRAMS") && count>0)
1202     // write class diagram using build-in generator
1203   {
1204     ClassDiagram diagram(this); // create a diagram of this class.
1205     ol.startClassDiagram();
1206     ol.disable(OutputGenerator::Man);
1207     ol.parseText(theTranslator->trClassDiagram(displayName()));
1208     ol.enable(OutputGenerator::Man);
1209     ol.endClassDiagram(diagram,getOutputFileBase(),displayName());
1210     renderDiagram = TRUE;
1211   }
1212
1213   if (renderDiagram) // if we already show the inheritance relations graphically,
1214                      // then hide the text version
1215   {
1216     ol.disableAllBut(OutputGenerator::Man);
1217   }
1218
1219   if (m_impl->inherits && (count=m_impl->inherits->count())>0)
1220   {
1221     ol.startParagraph();
1222     //parseText(ol,theTranslator->trInherits()+" ");
1223
1224     QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count());
1225     QRegExp marker("@[0-9]+");
1226     int index=0,newIndex,matchLen;
1227     // now replace all markers in inheritLine with links to the classes
1228     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
1229     {
1230       ol.parseText(inheritLine.mid(index,newIndex-index));
1231       bool ok;
1232       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
1233       BaseClassDef *bcd=m_impl->inherits->at(entryIndex);
1234       if (ok && bcd)
1235       {
1236         ClassDef *cd=bcd->classDef;
1237
1238         // use the class name but with the template arguments as given
1239         // in the inheritance relation
1240         QCString displayName = insertTemplateSpecifierInScope(
1241             cd->displayName(),bcd->templSpecifiers);
1242
1243         if (cd->isLinkable())
1244         {
1245           if (!Config_getString("GENERATE_TAGFILE").isEmpty())
1246           {
1247             Doxygen::tagFile << "    <base";
1248             if (bcd->prot==Protected)
1249             {
1250               Doxygen::tagFile << " protection=\"protected\"";
1251             }
1252             else if (bcd->prot==Private)
1253             {
1254               Doxygen::tagFile << " protection=\"private\"";
1255             }
1256             if (bcd->virt==Virtual)
1257             {
1258               Doxygen::tagFile << " virtualness=\"virtual\"";
1259             }
1260             Doxygen::tagFile << ">" << convertToXML(cd->name())
1261                              << "</base>" << endl;
1262           }
1263           ol.writeObjectLink(cd->getReference(),
1264                              cd->getOutputFileBase(),
1265                              cd->anchor(),
1266                              displayName);
1267         }
1268         else
1269         {
1270           ol.docify(displayName);
1271         }
1272       }
1273       else
1274       {
1275         err("invalid marker %d in inherits list!\n",entryIndex);
1276       }
1277       index=newIndex+matchLen;
1278     }
1279     ol.parseText(inheritLine.right(inheritLine.length()-index));
1280     ol.endParagraph();
1281   }
1282
1283   // write subclasses
1284   if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0)
1285   {
1286     ol.startParagraph();
1287     QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count());
1288     QRegExp marker("@[0-9]+");
1289     int index=0,newIndex,matchLen;
1290     // now replace all markers in inheritLine with links to the classes
1291     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
1292     {
1293       ol.parseText(inheritLine.mid(index,newIndex-index));
1294       bool ok;
1295       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
1296       BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex);
1297       if (ok && bcd)
1298       {
1299         ClassDef *cd=bcd->classDef;
1300         if (cd->isLinkable())
1301         {
1302           ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName());
1303         }
1304         else
1305         {
1306           ol.docify(cd->displayName());
1307         }
1308         writeInheritanceSpecifier(ol,bcd);
1309       }
1310       index=newIndex+matchLen;
1311     }
1312     ol.parseText(inheritLine.right(inheritLine.length()-index));
1313     ol.endParagraph();
1314   }
1315
1316   if (renderDiagram)
1317   {
1318     ol.enableAll();
1319   }
1320 }
1321
1322 void ClassDef::writeCollaborationGraph(OutputList &ol)
1323 {
1324   if (Config_getBool("HAVE_DOT") /*&& Config_getBool("COLLABORATION_GRAPH")*/)
1325   {
1326     DotClassGraph usageImplGraph(this,DotNode::Collaboration);
1327     if (!usageImplGraph.isTrivial())
1328     {
1329       ol.pushGeneratorState();
1330       ol.disable(OutputGenerator::Man);
1331       ol.startDotGraph();
1332       ol.parseText(theTranslator->trCollaborationDiagram(displayName()));
1333       ol.endDotGraph(usageImplGraph);
1334       ol.popGeneratorState();
1335     }
1336   }
1337 }
1338
1339 QCString ClassDef::includeStatement() const
1340 {
1341   SrcLangExt lang = getLanguage();
1342   bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
1343   if (isIDLorJava)
1344   {
1345     return "import";
1346   }
1347   else if (isObjectiveC())
1348   {
1349     return "#import ";
1350   }
1351   else
1352   {
1353     return "#include ";
1354   }
1355 }
1356
1357 void ClassDef::writeIncludeFiles(OutputList &ol)
1358 {
1359   if (m_impl->incInfo /*&& Config_getBool("SHOW_INCLUDE_FILES")*/)
1360   {
1361     QCString nm=m_impl->incInfo->includeName.isEmpty() ?
1362       (m_impl->incInfo->fileDef ?
1363        m_impl->incInfo->fileDef->docName().data() : ""
1364       ) :
1365       m_impl->incInfo->includeName.data();
1366     if (!nm.isEmpty())
1367     {
1368       ol.startParagraph();
1369       ol.startTypewriter();
1370       ol.docify(includeStatement());
1371       SrcLangExt lang = getLanguage();
1372       bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
1373       if (m_impl->incInfo->local || isIDLorJava)
1374         ol.docify("\"");
1375       else
1376         ol.docify("<");
1377       ol.pushGeneratorState();
1378       ol.disable(OutputGenerator::Html);
1379       ol.docify(nm);
1380       ol.disableAllBut(OutputGenerator::Html);
1381       ol.enable(OutputGenerator::Html);
1382       if (m_impl->incInfo->fileDef)
1383       {
1384         ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm);
1385       }
1386       else
1387       {
1388         ol.docify(nm);
1389       }
1390       ol.popGeneratorState();
1391       if (m_impl->incInfo->local || isIDLorJava)
1392         ol.docify("\"");
1393       else
1394         ol.docify(">");
1395       if (isIDLorJava)
1396         ol.docify(";");
1397       ol.endTypewriter();
1398       ol.endParagraph();
1399     }
1400   }
1401 }
1402
1403 #if 0
1404 void ClassDef::writeAllMembersLink(OutputList &ol)
1405 {
1406   // write link to list of all members (HTML only)
1407   if (m_impl->allMemberNameInfoSDict &&
1408       !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")
1409      )
1410   {
1411     ol.pushGeneratorState();
1412     ol.disableAllBut(OutputGenerator::Html);
1413     ol.startParagraph();
1414     ol.startTextLink(getMemberListFileName(),0);
1415     ol.parseText(theTranslator->trListOfAllMembers());
1416     ol.endTextLink();
1417     ol.endParagraph();
1418     ol.enableAll();
1419     ol.popGeneratorState();
1420   }
1421 }
1422 #endif
1423
1424 void ClassDef::writeMemberGroups(OutputList &ol,bool showInline)
1425 {
1426   // write user defined member groups
1427   if (m_impl->memberGroupSDict)
1428   {
1429     m_impl->memberGroupSDict->sort();
1430     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
1431     MemberGroup *mg;
1432     for (;(mg=mgli.current());++mgli)
1433     {
1434       if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
1435       {
1436         mg->writeDeclarations(ol,this,0,0,0,showInline);
1437       }
1438       else // add this group to the corresponding member section
1439       {
1440         //printf("addToDeclarationSection(%s)\n",mg->header().data());
1441         //mg->addToDeclarationSection();
1442       }
1443     }
1444   }
1445 }
1446
1447 void ClassDef::writeNestedClasses(OutputList &ol,const QCString &title)
1448 {
1449   // nested classes
1450   if (m_impl->innerClasses)
1451   {
1452     m_impl->innerClasses->writeDeclaration(ol,0,title,TRUE);
1453   }
1454 }
1455
1456 void ClassDef::writeInlineClasses(OutputList &ol)
1457 {
1458   if (m_impl->innerClasses)
1459   {
1460     m_impl->innerClasses->writeDocumentation(ol,this);
1461   }
1462 }
1463
1464 void ClassDef::startMemberDocumentation(OutputList &ol)
1465 {
1466   //printf("%s: ClassDef::startMemberDocumentation()\n",name().data());
1467   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
1468   {
1469     ol.disable(OutputGenerator::Html);
1470     Doxygen::suppressDocWarnings = TRUE;
1471   }
1472 }
1473
1474 void ClassDef::endMemberDocumentation(OutputList &ol)
1475 {
1476   //printf("%s: ClassDef::endMemberDocumentation()\n",name().data());
1477   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
1478   {
1479     ol.enable(OutputGenerator::Html);
1480     Doxygen::suppressDocWarnings = FALSE;
1481   }
1482 }
1483
1484 void ClassDef::startMemberDeclarations(OutputList &ol)
1485 {
1486   //printf("%s: ClassDef::startMemberDeclarations()\n",name().data());
1487   ol.startMemberSections();
1488 }
1489
1490 void ClassDef::endMemberDeclarations(OutputList &ol)
1491 {
1492   //printf("%s: ClassDef::endMemberDeclarations()\n",name().data());
1493   static bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB");
1494   if (!inlineInheritedMembers && countAdditionalInheritedMembers()>0)
1495   {
1496     ol.startMemberHeader("inherited");
1497     ol.parseText(theTranslator->trAdditionalInheritedMembers());
1498     ol.endMemberHeader();
1499     writeAdditionalInheritedMembers(ol);
1500   }
1501   ol.endMemberSections();
1502 }
1503
1504 void ClassDef::writeAuthorSection(OutputList &ol)
1505 {
1506   ol.pushGeneratorState();
1507   ol.disableAllBut(OutputGenerator::Man);
1508   ol.writeString("\n");
1509   ol.startGroupHeader();
1510   ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
1511   ol.endGroupHeader();
1512   ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
1513   ol.popGeneratorState();
1514 }
1515
1516
1517 void ClassDef::writeSummaryLinks(OutputList &ol)
1518 {
1519   ol.pushGeneratorState();
1520   ol.disableAllBut(OutputGenerator::Html);
1521   QListIterator<LayoutDocEntry> eli(
1522       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
1523   LayoutDocEntry *lde;
1524   bool first=TRUE;
1525   SrcLangExt lang = getLanguage();
1526
1527   if (lang!=SrcLangExt_VHDL)
1528   {
1529     for (eli.toFirst();(lde=eli.current());++eli)
1530     {
1531       if (lde->kind()==LayoutDocEntry::ClassNestedClasses &&
1532           m_impl->innerClasses  &&
1533           m_impl->innerClasses->declVisible()
1534          )
1535       {
1536         LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1537         ol.writeSummaryLink(0,"nested-classes",ls->title(lang),first);
1538         first=FALSE;
1539       }
1540       else if (lde->kind()==LayoutDocEntry::ClassAllMembersLink &&
1541                m_impl->allMemberNameInfoSDict &&
1542                !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")
1543               )
1544       {
1545         ol.writeSummaryLink(getMemberListFileName(),"all-members-list",theTranslator->trListOfAllMembers(),first);
1546         first=FALSE;
1547       }
1548       else if (lde->kind()== LayoutDocEntry::MemberDecl)
1549       {
1550         LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1551         MemberList * ml = getMemberList(lmd->type);
1552         if (ml && ml->declVisible())
1553         {
1554           ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
1555           first=FALSE;
1556         }
1557       }
1558     }
1559   }
1560   else // VDHL only
1561   {
1562     SDict<QCString>::Iterator li(m_impl->vhdlSummaryTitles);
1563     for (li.toFirst();li.current();++li)
1564     {
1565       ol.writeSummaryLink(0,li.current()->data(),li.current()->data(),first);
1566       first=FALSE;
1567     }
1568   }
1569   if (!first)
1570   {
1571     ol.writeString("  </div>\n");
1572   }
1573   ol.popGeneratorState();
1574 }
1575
1576 void ClassDef::writeTagFileMarker()
1577 {
1578   // write section to the tag file
1579   if (!Config_getString("GENERATE_TAGFILE").isEmpty())
1580   {
1581     Doxygen::tagFile << "  <compound kind=\"" << compoundTypeString();
1582     Doxygen::tagFile << "\"";
1583     if (isObjectiveC()) { Doxygen::tagFile << " objc=\"yes\""; }
1584     Doxygen::tagFile << ">" << endl;
1585     Doxygen::tagFile << "    <name>" << convertToXML(name()) << "</name>" << endl;
1586     Doxygen::tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
1587     if (!anchor().isEmpty())
1588     {
1589       Doxygen::tagFile << "    <anchor>" << convertToXML(anchor()) << "</anchor>" << endl;
1590     }
1591     QCString idStr = id();
1592     if (!idStr.isEmpty())
1593     {
1594       Doxygen::tagFile << "    <clangid>" << convertToXML(idStr) << "</clangid>" << endl;
1595     }
1596     if (m_impl->tempArgs)
1597     {
1598       ArgumentListIterator ali(*m_impl->tempArgs);
1599       Argument *a;
1600       for (;(a=ali.current());++ali)
1601       {
1602         Doxygen::tagFile << "    <templarg>" << convertToXML(a->name) << "</templarg>" << endl;
1603       }
1604     }
1605   }
1606 }
1607
1608 /** Write class documentation inside another container (i.e. a group) */
1609 void ClassDef::writeInlineDocumentation(OutputList &ol)
1610 {
1611   bool isSimple = m_impl->isSimple;
1612
1613   ol.addIndexItem(name(),0);
1614   //printf("ClassDef::writeInlineDocumentation(%s)\n",name().data());
1615   QListIterator<LayoutDocEntry> eli(
1616       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
1617   LayoutDocEntry *lde;
1618
1619   // part 1: anchor and title
1620   QCString s = compoundTypeString()+" "+name();
1621
1622   // part 1a
1623   ol.pushGeneratorState();
1624   ol.disableAllBut(OutputGenerator::Html);
1625   { // only HTML only
1626     ol.writeAnchor(0,anchor());
1627     ol.startMemberDoc(0,0,0,0,FALSE);
1628     ol.startMemberDocName(FALSE);
1629     ol.parseText(s);
1630     ol.endMemberDocName();
1631     ol.endMemberDoc(FALSE);
1632     ol.writeString("</div>");
1633     ol.startIndent();
1634   }
1635   ol.popGeneratorState();
1636
1637   // part 1b
1638   ol.pushGeneratorState();
1639   ol.disable(OutputGenerator::Html);
1640   ol.disable(OutputGenerator::Man);
1641   { // for LaTeX/RTF only
1642     ol.writeAnchor(getOutputFileBase(),anchor());
1643   }
1644   ol.popGeneratorState();
1645
1646   // part 1c
1647   ol.pushGeneratorState();
1648   ol.disable(OutputGenerator::Html);
1649   {
1650     // for LaTeX/RTF/Man
1651     ol.startGroupHeader(1);
1652     ol.parseText(s);
1653     ol.endGroupHeader(1);
1654   }
1655   ol.popGeneratorState();
1656
1657   SrcLangExt lang=getLanguage();
1658
1659   // part 2: the header and detailed description
1660   for (eli.toFirst();(lde=eli.current());++eli)
1661   {
1662     switch (lde->kind())
1663     {
1664       case LayoutDocEntry::BriefDesc:
1665         {
1666           // since we already shown the brief description in the
1667           // declaration part of the container, so we use this to
1668           // show the details on top.
1669           writeDetailedDocumentationBody(ol);
1670         }
1671         break;
1672       case LayoutDocEntry::ClassInheritanceGraph:
1673         writeInheritanceGraph(ol);
1674         break;
1675       case LayoutDocEntry::ClassCollaborationGraph:
1676         writeCollaborationGraph(ol);
1677         break;
1678       case LayoutDocEntry::MemberDeclStart:
1679         if (!isSimple) startMemberDeclarations(ol);
1680         break;
1681       case LayoutDocEntry::MemberDecl:
1682         {
1683           LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1684           if (!isSimple) writeMemberDeclarations(ol,lmd->type,lmd->title(lang),lmd->subtitle(lang),TRUE);
1685         }
1686         break;
1687       case LayoutDocEntry::MemberGroups:
1688         if (!isSimple) writeMemberGroups(ol,TRUE);
1689         break;
1690       case LayoutDocEntry::MemberDeclEnd:
1691         if (!isSimple) endMemberDeclarations(ol);
1692         break;
1693       case LayoutDocEntry::MemberDefStart:
1694         if (!isSimple) startMemberDocumentation(ol);
1695         break;
1696       case LayoutDocEntry::MemberDef:
1697         {
1698           LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
1699           if (isSimple)
1700           {
1701             writeSimpleMemberDocumentation(ol,lmd->type);
1702           }
1703           else
1704           {
1705             writeMemberDocumentation(ol,lmd->type,lmd->title(lang),TRUE);
1706           }
1707         }
1708         break;
1709       case LayoutDocEntry::MemberDefEnd:
1710         if (!isSimple) endMemberDocumentation(ol);
1711         break;
1712       default:
1713         break;
1714     }
1715   }
1716
1717   // part 3: close the block
1718   ol.pushGeneratorState();
1719   ol.disableAllBut(OutputGenerator::Html);
1720   { // HTML only
1721     ol.endIndent();
1722   }
1723   ol.popGeneratorState();
1724
1725   // part 4: write tag file information
1726   writeTagFileMarker();
1727 }
1728
1729 void ClassDef::writeMoreLink(OutputList &ol,const QCString &anchor)
1730 {
1731   // TODO: clean up this mess by moving it to
1732   // the output generators...
1733   static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
1734   static bool rtfHyperlinks = Config_getBool("RTF_HYPERLINKS");
1735   static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
1736
1737   // HTML only
1738   ol.pushGeneratorState();
1739   ol.disableAllBut(OutputGenerator::Html);
1740   ol.docify(" ");
1741   ol.startTextLink(getOutputFileBase(),
1742       anchor.isEmpty() ? QCString("details") : anchor);
1743   ol.parseText(theTranslator->trMore());
1744   ol.endTextLink();
1745   ol.popGeneratorState();
1746
1747   if (!anchor.isEmpty())
1748   {
1749     ol.pushGeneratorState();
1750     // LaTeX + RTF
1751     ol.disable(OutputGenerator::Html);
1752     ol.disable(OutputGenerator::Man);
1753     if (!(usePDFLatex && pdfHyperlinks))
1754     {
1755       ol.disable(OutputGenerator::Latex);
1756     }
1757     if (!rtfHyperlinks)
1758     {
1759       ol.disable(OutputGenerator::RTF);
1760     }
1761     ol.docify(" ");
1762     ol.startTextLink(getOutputFileBase(), anchor);
1763     ol.parseText(theTranslator->trMore());
1764     ol.endTextLink();
1765     // RTF only
1766     ol.disable(OutputGenerator::Latex);
1767     ol.writeString("\\par");
1768     ol.popGeneratorState();
1769   }
1770 }
1771
1772 bool ClassDef::visibleInParentsDeclList() const
1773 {
1774   static bool extractPrivate      = Config_getBool("EXTRACT_PRIVATE");
1775   static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
1776   static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES");
1777   bool linkable = isLinkable();
1778   return (!isAnonymous() && !isExtension() &&
1779           (protection()!=::Private || extractPrivate) &&
1780           (linkable || (!hideUndocClasses && (!isLocal() || extractLocalClasses)))
1781          );
1782 }
1783
1784 void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames)
1785 {
1786   //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
1787   //static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
1788   SrcLangExt lang = getLanguage();
1789   if (visibleInParentsDeclList())
1790   {
1791     if (!found) // first class
1792     {
1793       ol.startMemberHeader("nested-classes");
1794       if (header)
1795       {
1796         ol.parseText(header);
1797       }
1798       else if (lang==SrcLangExt_VHDL)
1799       {
1800         ol.parseText(VhdlDocGen::trVhdlType(VhdlDocGen::ARCHITECTURE,FALSE));
1801       }
1802       else
1803       {
1804         ol.parseText(lang==SrcLangExt_Fortran ?
1805             theTranslator->trDataTypes() :
1806             theTranslator->trCompounds());
1807       }
1808       ol.endMemberHeader();
1809       ol.startMemberList();
1810       found=TRUE;
1811     }
1812     if (!Config_getString("GENERATE_TAGFILE").isEmpty() &&
1813         !isReference())  // skip classes found in tag files
1814     {
1815       Doxygen::tagFile << "    <class kind=\"" << compoundTypeString()
1816         << "\">" << convertToXML(name()) << "</class>" << endl;
1817     }
1818     ol.startMemberDeclaration();
1819     ol.startMemberItem(anchor(),FALSE);
1820     QCString ctype = compoundTypeString();
1821     QCString cname = displayName(!localNames);
1822
1823     if (lang!=SrcLangExt_VHDL) // for VHDL we swap the name and the type
1824     {
1825       ol.writeString(ctype);
1826       ol.writeString(" ");
1827       ol.insertMemberAlign();
1828     }
1829     if (isLinkable())
1830     {
1831       ol.writeObjectLink(getReference(),
1832           getOutputFileBase(),
1833           anchor(),
1834           cname
1835           );
1836     }
1837     else
1838     {
1839       ol.startBold();
1840       ol.docify(cname);
1841       ol.endBold();
1842     }
1843     if (lang==SrcLangExt_VHDL) // now write the type
1844     {
1845       ol.writeString(" ");
1846       ol.insertMemberAlign();
1847       ol.writeString(VhdlDocGen::getProtectionName((VhdlDocGen::VhdlClasses)protection()));
1848     }
1849     ol.endMemberItem();
1850
1851     // add the brief description if available
1852     if (!briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))
1853     {
1854       DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
1855                                 briefDescription(),FALSE,FALSE,0,TRUE,FALSE);
1856       if (rootNode && !rootNode->isEmpty())
1857       {
1858         ol.startMemberDescription(anchor());
1859         ol.writeDoc(rootNode,this,0);
1860         if (isLinkableInProject())
1861         {
1862           writeMoreLink(ol,anchor());
1863         }
1864         ol.endMemberDescription();
1865       }
1866       delete rootNode;
1867     }
1868     ol.endMemberDeclaration(anchor(),0);
1869   }
1870 }
1871
1872 void ClassDef::addClassAttributes(OutputList &ol)
1873 {
1874   QStrList sl;
1875   if (isFinal())    sl.append("final");
1876   if (isSealed())   sl.append("sealed");
1877   if (isAbstract()) sl.append("abstract");
1878   if (getLanguage()==SrcLangExt_IDL && isPublished()) sl.append("published");
1879
1880   ol.pushGeneratorState();
1881   ol.disableAllBut(OutputGenerator::Html);
1882   if (sl.count()>0)
1883   {
1884     ol.startLabels();
1885     const char *s=sl.first();
1886     while (s)
1887     {
1888       const char *ns = sl.next();
1889       ol.writeLabel(s,ns==0);
1890       s=ns;
1891     }
1892     ol.endLabels();
1893   }
1894   ol.popGeneratorState();
1895 }
1896
1897 void ClassDef::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/)
1898 {
1899   ol.startContents();
1900
1901   QCString pageType = " ";
1902   pageType += compoundTypeString();
1903   toupper(pageType.at(1));
1904
1905   writeTagFileMarker();
1906
1907   Doxygen::indexList->addIndexItem(this,0);
1908
1909   if (Doxygen::searchIndex)
1910   {
1911     Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
1912     Doxygen::searchIndex->addWord(localName(),TRUE);
1913   }
1914   bool exampleFlag=hasExamples();
1915
1916   //---------------------------------------- start flexible part -------------------------------
1917
1918   SrcLangExt lang = getLanguage();
1919
1920   QListIterator<LayoutDocEntry> eli(
1921       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
1922   LayoutDocEntry *lde;
1923   for (eli.toFirst();(lde=eli.current());++eli)
1924   {
1925     switch (lde->kind())
1926     {
1927       case LayoutDocEntry::BriefDesc:
1928         writeBriefDescription(ol,exampleFlag);
1929         break;
1930       case LayoutDocEntry::ClassIncludes:
1931         writeIncludeFiles(ol);
1932         break;
1933       case LayoutDocEntry::ClassInheritanceGraph:
1934         writeInheritanceGraph(ol);
1935         break;
1936       case LayoutDocEntry::ClassCollaborationGraph:
1937         writeCollaborationGraph(ol);
1938         break;
1939       case LayoutDocEntry::ClassAllMembersLink:
1940         //writeAllMembersLink(ol); // this is now part of the summary links
1941         break;
1942       case LayoutDocEntry::MemberDeclStart:
1943         startMemberDeclarations(ol);
1944         break;
1945       case LayoutDocEntry::MemberGroups:
1946         writeMemberGroups(ol);
1947         break;
1948       case LayoutDocEntry::MemberDecl:
1949         {
1950           LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
1951           writeMemberDeclarations(ol,lmd->type,lmd->title(lang),lmd->subtitle(lang));
1952         }
1953         break;
1954       case LayoutDocEntry::ClassNestedClasses:
1955         {
1956           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1957           writeNestedClasses(ol,ls->title(lang));
1958         }
1959         break;
1960       case LayoutDocEntry::MemberDeclEnd:
1961         endMemberDeclarations(ol);
1962         break;
1963       case LayoutDocEntry::DetailedDesc:
1964         {
1965           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
1966           writeDetailedDescription(ol,pageType,exampleFlag,ls->title(lang));
1967         }
1968         break;
1969       case LayoutDocEntry::MemberDefStart:
1970         startMemberDocumentation(ol);
1971         break;
1972       case LayoutDocEntry::ClassInlineClasses:
1973         writeInlineClasses(ol);
1974         break;
1975       case LayoutDocEntry::MemberDef:
1976         {
1977           LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
1978           writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
1979         }
1980         break;
1981       case LayoutDocEntry::MemberDefEnd:
1982         endMemberDocumentation(ol);
1983         break;
1984       case LayoutDocEntry::ClassUsedFiles:
1985         showUsedFiles(ol);
1986         break;
1987       case LayoutDocEntry::AuthorSection:
1988         writeAuthorSection(ol);
1989         break;
1990       case LayoutDocEntry::NamespaceNestedNamespaces:
1991       case LayoutDocEntry::NamespaceNestedConstantGroups:
1992       case LayoutDocEntry::NamespaceClasses:
1993       case LayoutDocEntry::NamespaceInlineClasses:
1994       case LayoutDocEntry::FileClasses:
1995       case LayoutDocEntry::FileNamespaces:
1996       case LayoutDocEntry::FileConstantGroups:
1997       case LayoutDocEntry::FileIncludes:
1998       case LayoutDocEntry::FileIncludeGraph:
1999       case LayoutDocEntry::FileIncludedByGraph:
2000       case LayoutDocEntry::FileSourceLink:
2001       case LayoutDocEntry::FileInlineClasses:
2002       case LayoutDocEntry::GroupClasses:
2003       case LayoutDocEntry::GroupInlineClasses:
2004       case LayoutDocEntry::GroupNamespaces:
2005       case LayoutDocEntry::GroupDirs:
2006       case LayoutDocEntry::GroupNestedGroups:
2007       case LayoutDocEntry::GroupFiles:
2008       case LayoutDocEntry::GroupGraph:
2009       case LayoutDocEntry::GroupPageDocs:
2010       case LayoutDocEntry::DirSubDirs:
2011       case LayoutDocEntry::DirFiles:
2012       case LayoutDocEntry::DirGraph:
2013         err("Internal inconsistency: member %d should not be part of "
2014             "LayoutDocManager::Class entry list\n",lde->kind());
2015         break;
2016     }
2017   }
2018
2019   if (!Config_getString("GENERATE_TAGFILE").isEmpty())
2020   {
2021     writeDocAnchorsToTagFile();
2022     Doxygen::tagFile << "  </compound>" << endl;
2023   }
2024   ol.endContents();
2025 }
2026
2027 QCString ClassDef::title() const
2028 {
2029   QCString pageTitle;
2030   SrcLangExt lang = getLanguage();
2031
2032   if (lang==SrcLangExt_Fortran)
2033   {
2034     pageTitle = theTranslator->trCompoundReferenceFortran(displayName(),
2035               m_impl->compType,
2036               m_impl->tempArgs != 0);
2037   }
2038   else if (lang==SrcLangExt_VHDL)
2039   {
2040     pageTitle = VhdlDocGen::getClassTitle(this)+" Reference";
2041   }
2042   else if (isJavaEnum())
2043   {
2044     pageTitle = theTranslator->trEnumReference(displayName());
2045   }
2046   else if (m_impl->compType==Service)
2047   {
2048     pageTitle = theTranslator->trServiceReference(displayName());
2049   }
2050   else if (m_impl->compType==Singleton)
2051   {
2052     pageTitle = theTranslator->trSingletonReference(displayName());
2053   }
2054   else
2055   {
2056     pageTitle = theTranslator->trCompoundReference(displayName(),
2057               m_impl->compType == Interface && getLanguage()==SrcLangExt_ObjC ? Class : m_impl->compType,
2058               m_impl->tempArgs != 0);
2059   }
2060   return pageTitle;
2061 }
2062
2063 // write all documentation for this class
2064 void ClassDef::writeDocumentation(OutputList &ol)
2065 {
2066   static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
2067   //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
2068   //static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2069   QCString pageTitle = title();
2070
2071   startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,!generateTreeView);
2072   if (!generateTreeView)
2073   {
2074     if (getOuterScope()!=Doxygen::globalScope)
2075     {
2076       writeNavigationPath(ol);
2077     }
2078     ol.endQuickIndices();
2079   }
2080
2081   startTitle(ol,getOutputFileBase(),this);
2082   ol.parseText(pageTitle);
2083   addClassAttributes(ol);
2084   addGroupListToTitle(ol,this);
2085   endTitle(ol,getOutputFileBase(),displayName());
2086   writeDocumentationContents(ol,pageTitle);
2087
2088   endFileWithNavPath(this,ol);
2089
2090   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
2091   {
2092     writeMemberPages(ol);
2093   }
2094 }
2095
2096 void ClassDef::writeMemberPages(OutputList &ol)
2097 {
2098   ///////////////////////////////////////////////////////////////////////////
2099   //// Member definitions on separate pages
2100   ///////////////////////////////////////////////////////////////////////////
2101
2102   ol.pushGeneratorState();
2103   ol.disableAllBut(OutputGenerator::Html);
2104
2105   QListIterator<MemberList> mli(m_impl->memberLists);
2106   MemberList *ml;
2107   for (mli.toFirst();(ml=mli.current());++mli)
2108   {
2109     ml->countDocMembers();
2110     if (ml->numDocMembers()>0 && (ml->listType()&MemberListType_detailedLists))
2111     {
2112       ml->writeDocumentationPage(ol,displayName(),this);
2113     }
2114   }
2115
2116   ol.popGeneratorState();
2117 }
2118
2119 void ClassDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
2120 {
2121   static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
2122
2123   ol.writeString("      <div class=\"navtab\">\n");
2124   ol.writeString("        <table>\n");
2125
2126   if (m_impl->allMemberNameInfoSDict)
2127   {
2128     MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
2129     MemberNameInfo *mni;
2130     for (;(mni=mnili.current());++mnili)
2131     {
2132       MemberNameInfoIterator mnii(*mni);
2133       MemberInfo *mi;
2134       for (mnii.toFirst();(mi=mnii.current());++mnii)
2135       {
2136         MemberDef *md=mi->memberDef;
2137         if (md->getClassDef()==this && md->isLinkable() && !md->isEnumValue())
2138         {
2139           ol.writeString("          <tr><td class=\"navtab\">");
2140           if (md->isLinkableInProject())
2141           {
2142             if (md==currentMd) // selected item => highlight
2143             {
2144               ol.writeString("<a class=\"qindexHL\" ");
2145             }
2146             else
2147             {
2148               ol.writeString("<a class=\"qindex\" ");
2149             }
2150             ol.writeString("href=\"");
2151             if (createSubDirs) ol.writeString("../../");
2152             ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
2153             ol.writeString("\">");
2154             ol.writeString(convertToHtml(md->name()));
2155             ol.writeString("</a>");
2156           }
2157           ol.writeString("</td></tr>\n");
2158         }
2159       }
2160     }
2161   }
2162
2163   ol.writeString("        </table>\n");
2164   ol.writeString("      </div>\n");
2165 }
2166
2167
2168
2169 void ClassDef::writeDocumentationForInnerClasses(OutputList &ol)
2170 {
2171   // write inner classes after the parent, so the tag files contain
2172   // the definition in proper order!
2173   if (m_impl->innerClasses)
2174   {
2175     ClassSDict::Iterator cli(*m_impl->innerClasses);
2176     ClassDef *innerCd;
2177     for (cli.toFirst();(innerCd=cli.current());++cli)
2178     {
2179       if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 &&
2180           protectionLevelVisible(innerCd->protection()) &&
2181          !innerCd->isEmbeddedInOuterScope()
2182          )
2183       {
2184         msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name()));
2185         innerCd->writeDocumentation(ol);
2186         innerCd->writeMemberList(ol);
2187       }
2188       innerCd->writeDocumentationForInnerClasses(ol);
2189     }
2190   }
2191 }
2192
2193 // write the list of all (inherited) members for this class
2194 void ClassDef::writeMemberList(OutputList &ol)
2195 {
2196   static bool cOpt    = Config_getBool("OPTIMIZE_OUTPUT_FOR_C");
2197   //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2198   static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
2199   if (m_impl->allMemberNameInfoSDict==0 || cOpt) return;
2200   // only for HTML
2201   ol.pushGeneratorState();
2202   ol.disableAllBut(OutputGenerator::Html);
2203
2204   QCString memListFile = getMemberListFileName();
2205   startFile(ol,memListFile,memListFile,theTranslator->trMemberList(),
2206             HLI_ClassVisible,!generateTreeView,getOutputFileBase());
2207   if (!generateTreeView)
2208   {
2209     if (getOuterScope()!=Doxygen::globalScope)
2210     {
2211       writeNavigationPath(ol);
2212     }
2213     ol.endQuickIndices();
2214   }
2215   startTitle(ol,0);
2216   ol.parseText(displayName()+" "+theTranslator->trMemberList());
2217   endTitle(ol,0,0);
2218   ol.startContents();
2219   ol.startParagraph();
2220   ol.parseText(theTranslator->trThisIsTheListOfAllMembers());
2221   ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),displayName());
2222   ol.parseText(theTranslator->trIncludingInheritedMembers());
2223   ol.endParagraph();
2224
2225   //ol.startItemList();
2226   ol.writeString("<table class=\"directory\">\n");
2227
2228   int idx=0;
2229   //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first();
2230   MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict);
2231   MemberNameInfo *mni;
2232   for (mnii.toFirst();(mni=mnii.current());++mnii)
2233   {
2234     MemberNameInfoIterator it(*mni);
2235     MemberInfo *mi;
2236     for (;(mi=it.current());++it)
2237     {
2238       MemberDef *md=mi->memberDef;
2239       ClassDef  *cd=md->getClassDef();
2240       Protection prot = mi->prot;
2241       Specifier virt=md->virtualness();
2242
2243       //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n",
2244       //    name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited);
2245
2246       if (cd && !md->name().isEmpty() && md->name()[0]!='@')
2247       {
2248         bool memberWritten=FALSE;
2249         if (cd->isLinkable() && md->isLinkable())
2250           // create a link to the documentation
2251         {
2252           QCString name=mi->ambiguityResolutionScope+md->name();
2253           //ol.writeListItem();
2254           ol.writeString("  <tr");
2255           if ((idx&1)==0) ol.writeString(" class=\"even\"");
2256           idx++;
2257           ol.writeString("><td class=\"entry\">");
2258           if (cd->isObjectiveC())
2259           {
2260             if (md->isObjCMethod())
2261             {
2262               if (md->isStatic())
2263                 ol.writeString("+&#160;</td><td>");
2264               else
2265                 ol.writeString("-&#160;</td><td>");
2266             }
2267             else
2268               ol.writeString("</td><td class=\"entry\">");
2269           }
2270           if (md->isObjCMethod())
2271           {
2272             ol.writeObjectLink(md->getReference(),
2273                 md->getOutputFileBase(),
2274                 md->anchor(),md->name());
2275           }
2276           else
2277           {
2278             //Definition *bd = md->getGroupDef();
2279             //if (bd==0) bd=cd;
2280             ol.writeObjectLink(md->getReference(),
2281                 md->getOutputFileBase(),
2282                 md->anchor(),name);
2283
2284             if ( md->isFunction() || md->isSignal() || md->isSlot() ||
2285                 (md->isFriend() && md->argsString()))
2286               ol.docify(md->argsString());
2287             else if (md->isEnumerate())
2288               ol.parseText(" "+theTranslator->trEnumName());
2289             else if (md->isEnumValue())
2290               ol.parseText(" "+theTranslator->trEnumValue());
2291             else if (md->isTypedef())
2292               ol.docify(" typedef");
2293             else if (md->isFriend() && !qstrcmp(md->typeString(),"friend class"))
2294               ol.docify(" class");
2295             //ol.writeString("\n");
2296           }
2297           ol.writeString("</td>");
2298           memberWritten=TRUE;
2299         }
2300         else if (!cd->isArtificial() &&
2301                  !Config_getBool("HIDE_UNDOC_MEMBERS") &&
2302                   (protectionLevelVisible(md->protection()) || md->isFriend())
2303                 ) // no documentation,
2304                   // generate link to the class instead.
2305         {
2306           //ol.writeListItem();
2307           ol.writeString("  <tr bgcolor=\"#f0f0f0\"");
2308           if ((idx&1)==0) ol.writeString(" class=\"even\"");
2309           idx++;
2310           ol.writeString("><td class=\"entry\">");
2311           if (cd->isObjectiveC())
2312           {
2313             if (md->isObjCMethod())
2314             {
2315               if (md->isStatic())
2316                 ol.writeString("+&#160;</td><td class=\"entry\">");
2317               else
2318                 ol.writeString("-&#160;</td><td class=\"entry\">");
2319             }
2320             else
2321               ol.writeString("</td><td class=\"entry\">");
2322           }
2323           ol.startBold();
2324           ol.docify(md->name());
2325           ol.endBold();
2326           if (!md->isObjCMethod())
2327           {
2328             if ( md->isFunction() || md->isSignal() || md->isSlot() )
2329               ol.docify(md->argsString());
2330             else if (md->isEnumerate())
2331               ol.parseText(" "+theTranslator->trEnumName());
2332             else if (md->isEnumValue())
2333               ol.parseText(" "+theTranslator->trEnumValue());
2334             else if (md->isTypedef())
2335               ol.docify(" typedef");
2336           }
2337           ol.writeString(" (");
2338           ol.parseText(theTranslator->trDefinedIn()+" ");
2339           if (cd->isLinkable())
2340           {
2341             ol.writeObjectLink(
2342                 cd->getReference(),
2343                 cd->getOutputFileBase(),
2344                 cd->anchor(),
2345                 cd->displayName());
2346           }
2347           else
2348           {
2349             ol.startBold();
2350             ol.docify(cd->displayName());
2351             ol.endBold();
2352           }
2353           ol.writeString(")");
2354           ol.writeString("</td>");
2355           memberWritten=TRUE;
2356         }
2357         if (memberWritten)
2358         {
2359           ol.writeString("<td class=\"entry\">");
2360           ol.writeObjectLink(cd->getReference(),
2361                              cd->getOutputFileBase(),
2362                              cd->anchor(),
2363                              md->category() ?
2364                                 md->category()->displayName() :
2365                                 cd->displayName());
2366           ol.writeString("</td>");
2367           ol.writeString("<td class=\"entry\">");
2368         }
2369         SrcLangExt lang = md->getLanguage();
2370         if (
2371             (prot!=Public || (virt!=Normal && getLanguage()!=SrcLangExt_ObjC) ||
2372              md->isFriend() || md->isRelated() || md->isExplicit() ||
2373              md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) ||
2374              md->isSignal() || md->isSlot() ||
2375              (getLanguage()==SrcLangExt_IDL &&
2376               (md->isOptional() || md->isAttribute() || md->isUNOProperty())) ||
2377              md->isStatic() || lang==SrcLangExt_VHDL
2378             )
2379             && memberWritten)
2380         {
2381           ol.writeString("<span class=\"mlabel\">");
2382           QStrList sl;
2383           if (lang==SrcLangExt_VHDL)
2384           {
2385             sl.append(VhdlDocGen::trVhdlType(md->getMemberSpecifiers())); //append vhdl type
2386           }
2387           else if (md->isFriend()) sl.append("friend");
2388           else if (md->isRelated()) sl.append("related");
2389           else
2390           {
2391             if (Config_getBool("INLINE_INFO") && md->isInline())
2392                                        sl.append("inline");
2393             if (md->isExplicit())      sl.append("explicit");
2394             if (md->isMutable())       sl.append("mutable");
2395             if (prot==Protected)       sl.append("protected");
2396             else if (prot==Private)    sl.append("private");
2397             else if (prot==Package)    sl.append("package");
2398             if (virt==Virtual && getLanguage()!=SrcLangExt_ObjC)
2399                                        sl.append("virtual");
2400             else if (virt==Pure)       sl.append("pure virtual");
2401             if (md->isStatic())        sl.append("static");
2402             if (md->isSignal())        sl.append("signal");
2403             if (md->isSlot())          sl.append("slot");
2404 // this is the extra member page
2405             if (md->isOptional())      sl.append("optional");
2406             if (md->isAttribute())     sl.append("attribute");
2407             if (md->isUNOProperty())   sl.append("property");
2408             if (md->isReadonly())      sl.append("readonly");
2409             if (md->isBound())         sl.append("bound");
2410             if (md->isRemovable())     sl.append("removable");
2411             if (md->isConstrained())   sl.append("constrained");
2412             if (md->isTransient())     sl.append("transient");
2413             if (md->isMaybeVoid())     sl.append("maybevoid");
2414             if (md->isMaybeDefault())  sl.append("maybedefault");
2415             if (md->isMaybeAmbiguous())sl.append("maybeambiguous");
2416           }
2417           const char *s=sl.first();
2418           while (s)
2419           {
2420             ol.docify(s);
2421             s=sl.next();
2422             if (s) ol.writeString("</span><span class=\"mlabel\">");
2423           }
2424           ol.writeString("</span>");
2425         }
2426         if (memberWritten)
2427         {
2428           ol.writeString("</td>");
2429           ol.writeString("</tr>\n");
2430         }
2431       }
2432     }
2433   }
2434   //ol.endItemList();
2435
2436   ol.writeString("</table>");
2437
2438   endFile(ol);
2439   ol.popGeneratorState();
2440 }
2441
2442
2443 // add a reference to an example
2444 bool ClassDef::addExample(const char *anchor,const char *nameStr,
2445     const char *file)
2446 {
2447   if (m_impl->exampleSDict==0)
2448   {
2449     m_impl->exampleSDict = new ExampleSDict;
2450     m_impl->exampleSDict->setAutoDelete(TRUE);
2451   }
2452   if (!m_impl->exampleSDict->find(nameStr))
2453   {
2454     Example *e=new Example;
2455     e->anchor=anchor;
2456     e->name=nameStr;
2457     e->file=file;
2458     m_impl->exampleSDict->inSort(nameStr,e);
2459     return TRUE;
2460   }
2461   return FALSE;
2462 }
2463
2464 // returns TRUE if this class is used in an example
2465 bool ClassDef::hasExamples() const
2466 {
2467   bool result=FALSE;
2468   if (m_impl->exampleSDict)
2469     result = m_impl->exampleSDict->count()>0;
2470   return result;
2471 }
2472
2473
2474 void ClassDef::setTemplateArguments(ArgumentList *al)
2475 {
2476   if (al==0) return;
2477   if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
2478   m_impl->tempArgs=new ArgumentList;
2479   ArgumentListIterator ali(*al);
2480   Argument *a;
2481   for (;(a=ali.current());++ali)
2482   {
2483     m_impl->tempArgs->append(new Argument(*a));
2484   }
2485 }
2486
2487 void ClassDef::setTypeConstraints(ArgumentList *al)
2488 {
2489   if (al==0) return;
2490   if (!m_impl->typeConstraints) delete m_impl->typeConstraints;
2491   m_impl->typeConstraints = new ArgumentList;
2492   ArgumentListIterator ali(*al);
2493   Argument *a;
2494   for (;(a=ali.current());++ali)
2495   {
2496     m_impl->typeConstraints->append(new Argument(*a));
2497   }
2498 }
2499
2500 /*! Returns \c TRUE iff this class or a class inheriting from this class
2501  *  is \e not defined in an external tag file.
2502  */
2503 bool ClassDef::hasNonReferenceSuperClass()
2504 {
2505   bool found=!isReference() && isLinkableInProject() && !isHidden();
2506   if (found)
2507   {
2508     return TRUE; // we're done if this class is not a reference
2509   }
2510   if (m_impl->inheritedBy)
2511   {
2512     BaseClassListIterator bcli(*m_impl->inheritedBy);
2513     for ( ; bcli.current() && !found ; ++bcli ) // for each super class
2514     {
2515       ClassDef *bcd=bcli.current()->classDef;
2516       // recurse into the super class branch
2517       found = found || bcd->hasNonReferenceSuperClass();
2518       if (!found)
2519       {
2520         // look for template instances that might have non-reference super classes
2521         QDict<ClassDef> *cil = bcd->getTemplateInstances();
2522         if (cil)
2523         {
2524           QDictIterator<ClassDef> tidi(*cil);
2525           for ( ; tidi.current() && !found ; ++tidi) // for each template instance
2526           {
2527             // recurse into the template instance branch
2528             found = found || tidi.current()->hasNonReferenceSuperClass();
2529           }
2530         }
2531       }
2532     }
2533   }
2534   return found;
2535 }
2536
2537 /*! called from MemberDef::writeDeclaration() to (recusively) write the
2538  *  definition of an anonymous struct, union or class.
2539  */
2540 void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup,
2541     ClassDef *inheritedFrom,const char *inheritId)
2542 {
2543   //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup);
2544
2545   ol.docify(compoundTypeString());
2546   QCString cn = displayName(FALSE);
2547   if (!cn.isEmpty())
2548   {
2549     ol.docify(" ");
2550     if (md && isLinkable())
2551     {
2552       ol.writeObjectLink(0,0,md->anchor(),cn);
2553     }
2554     else
2555     {
2556       ol.startBold();
2557       ol.docify(cn);
2558       ol.endBold();
2559     }
2560   }
2561   ol.docify(" {");
2562   ol.endMemberItem();
2563
2564   // write user defined member groups
2565   if (m_impl->memberGroupSDict)
2566   {
2567     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
2568     MemberGroup *mg;
2569     for (;(mg=mgli.current());++mgli)
2570     {
2571       mg->setInGroup(inGroup);
2572       mg->writePlainDeclarations(ol,this,0,0,0,inheritedFrom,inheritId);
2573     }
2574   }
2575
2576   QListIterator<LayoutDocEntry> eli(
2577       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
2578   LayoutDocEntry *lde;
2579   for (eli.toFirst();(lde=eli.current());++eli)
2580   {
2581     if (lde->kind()==LayoutDocEntry::MemberDecl)
2582     {
2583       LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
2584       writePlainMemberDeclaration(ol,lmd->type,inGroup,inheritedFrom,inheritId);
2585     }
2586   }
2587 }
2588
2589 /*! a link to this class is possible within this project */
2590 bool ClassDef::isLinkableInProject() const
2591 {
2592   static bool extractLocal   = Config_getBool("EXTRACT_LOCAL_CLASSES");
2593   static bool extractStatic  = Config_getBool("EXTRACT_STATIC");
2594   static bool hideUndoc      = Config_getBool("HIDE_UNDOC_CLASSES");
2595   if (m_impl->templateMaster)
2596   {
2597     return m_impl->templateMaster->isLinkableInProject();
2598   }
2599   else
2600   {
2601     return !name().isEmpty() &&                    /* has a name */
2602       !isArtificial() && !isHidden() &&            /* not hidden */
2603       !isAnonymous() &&                            /* not anonymous */
2604       protectionLevelVisible(m_impl->prot)      && /* private/internal */
2605       (!m_impl->isLocal      || extractLocal)   && /* local */
2606       (hasDocumentation()    || !hideUndoc)     && /* documented */
2607       (!m_impl->isStatic     || extractStatic)  && /* static */
2608       !isReference();                              /* not an external reference */
2609   }
2610 }
2611
2612 bool ClassDef::isLinkable() const
2613 {
2614   if (m_impl->templateMaster)
2615   {
2616     return m_impl->templateMaster->isLinkable();
2617   }
2618   else
2619   {
2620     return isLinkableInProject() || isReference();
2621   }
2622 }
2623
2624
2625 /*! the class is visible in a class diagram, or class hierarchy */
2626 bool ClassDef::isVisibleInHierarchy()
2627 {
2628   static bool allExternals     = Config_getBool("ALLEXTERNALS");
2629   static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
2630   static bool extractStatic    = Config_getBool("EXTRACT_STATIC");
2631
2632   return // show all classes or a subclass is visible
2633       (allExternals || hasNonReferenceSuperClass()) &&
2634       // and not an anonymous compound
2635       !isAnonymous() &&
2636       // not an artificially introduced class
2637       /*!isArtificial() &&*/  // 1.8.2: allowed these to appear
2638       // and not privately inherited
2639       protectionLevelVisible(m_impl->prot) &&
2640       // documented or shown anyway or documentation is external
2641       (hasDocumentation() ||
2642        !hideUndocClasses ||
2643        (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) ||
2644        isReference()
2645       ) &&
2646       // is not part of an unnamed namespace or shown anyway
2647       (!m_impl->isStatic || extractStatic);
2648 }
2649
2650 bool ClassDef::hasDocumentation() const
2651 {
2652   return Definition::hasDocumentation();
2653 }
2654
2655 //----------------------------------------------------------------------
2656 // recursive function:
2657 // returns TRUE iff class definition `bcd' represents an (in)direct base
2658 // class of class definition `cd'.
2659
2660 bool ClassDef::isBaseClass(ClassDef *bcd, bool followInstances,int level)
2661 {
2662   bool found=FALSE;
2663   //printf("isBaseClass(cd=%s) looking for %s\n",name().data(),bcd->name().data());
2664   if (level>256)
2665   {
2666     err("Possible recursive class relation while inside %s and looking for base class %s\n",qPrint(name()),qPrint(bcd->name()));
2667     return FALSE;
2668   }
2669   if (baseClasses())
2670   {
2671     // Beware: trying to optimise the iterator away using ->first() & ->next()
2672     // causes bug 625531
2673     BaseClassListIterator bcli(*baseClasses());
2674     for ( ; bcli.current() && !found ; ++bcli)
2675     {
2676       ClassDef *ccd=bcli.current()->classDef;
2677       if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
2678       //printf("isBaseClass() baseclass %s\n",ccd->name().data());
2679       if (ccd==bcd)
2680         found=TRUE;
2681       else
2682         found=ccd->isBaseClass(bcd,followInstances,level+1);
2683     }
2684   }
2685   return found;
2686 }
2687
2688 //----------------------------------------------------------------------
2689
2690 bool ClassDef::isSubClass(ClassDef *cd,int level)
2691 {
2692   bool found=FALSE;
2693   if (level>256)
2694   {
2695     err("Possible recursive class relation while inside %s and looking for derived class %s\n",qPrint(name()),qPrint(cd->name()));
2696     return FALSE;
2697   }
2698   if (subClasses())
2699   {
2700     BaseClassListIterator bcli(*subClasses());
2701     for ( ; bcli.current() && !found ; ++bcli)
2702     {
2703       ClassDef *ccd=bcli.current()->classDef;
2704       if (ccd==cd)
2705         found=TRUE;
2706       else
2707         found=ccd->isSubClass(cd,level+1);
2708     }
2709   }
2710   return found;
2711 }
2712
2713 //----------------------------------------------------------------------------
2714
2715 static bool isStandardFunc(MemberDef *md)
2716 {
2717   return md->name()=="operator=" || // assignment operator
2718          md->isConstructor() ||     // constructor
2719          md->isDestructor();        // destructor
2720 }
2721
2722 /*!
2723  * recusively merges the `all members' lists of a class base
2724  * with that of this class. Must only be called for classes without
2725  * subclasses!
2726  */
2727 void ClassDef::mergeMembers()
2728 {
2729   if (m_impl->membersMerged) return;
2730
2731   //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
2732   //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2733   SrcLangExt lang = getLanguage();
2734   QCString sep=getLanguageSpecificSeparator(lang,TRUE);
2735   int sepLen = sep.length();
2736
2737   m_impl->membersMerged=TRUE;
2738   //printf("  mergeMembers for %s\n",name().data());
2739   bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB" );
2740   if (baseClasses())
2741   {
2742     //printf("  => has base classes!\n");
2743     BaseClassListIterator bcli(*baseClasses());
2744     BaseClassDef *bcd;
2745     for ( ; (bcd=bcli.current()) ; ++bcli )
2746     {
2747       ClassDef *bClass=bcd->classDef;
2748
2749       // merge the members in the base class of this inheritance branch first
2750       bClass->mergeMembers();
2751
2752       MemberNameInfoSDict *srcMnd  = bClass->memberNameInfoSDict();
2753       MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
2754
2755       if (srcMnd)
2756       {
2757         MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
2758         MemberNameInfo *srcMni;
2759         for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
2760         {
2761           //printf("    Base member name %s\n",srcMni->memberName());
2762           MemberNameInfo *dstMni;
2763           if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName())))
2764             // a member with that name is already in the class.
2765             // the member may hide or reimplement the one in the sub class
2766             // or there may be another path to the base class that is already
2767             // visited via another branch in the class hierarchy.
2768           {
2769             MemberNameInfoIterator srcMnii(*srcMni);
2770             MemberInfo *srcMi;
2771             for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
2772             {
2773               MemberDef *srcMd = srcMi->memberDef;
2774               bool found=FALSE;
2775               bool ambigue=FALSE;
2776               bool hidden=FALSE;
2777               MemberNameInfoIterator dstMnii(*dstMni);
2778               MemberInfo *dstMi;
2779               ClassDef *srcCd = srcMd->getClassDef();
2780               for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
2781               {
2782                 MemberDef *dstMd = dstMi->memberDef;
2783                 if (srcMd!=dstMd) // different members
2784                 {
2785                   ClassDef *dstCd = dstMd->getClassDef();
2786                   //printf("  Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data());
2787                   if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE))
2788                     // member is in the same or a base class
2789                   {
2790                     ArgumentList *srcAl = srcMd->argumentList();
2791                     ArgumentList *dstAl = dstMd->argumentList();
2792                     found=matchArguments2(
2793                         srcMd->getOuterScope(),srcMd->getFileDef(),srcAl,
2794                         dstMd->getOuterScope(),dstMd->getFileDef(),dstAl,
2795                         TRUE
2796                         );
2797                     //printf("  Yes, matching (%s<->%s): %d\n",
2798                     //    argListToString(srcMd->argumentList()).data(),
2799                     //    argListToString(dstMd->argumentList()).data(),
2800                     //    found);
2801                     hidden = hidden  || !found;
2802                   }
2803                   else // member is in a non base class => multiple inheritance
2804                     // using the same base class.
2805                   {
2806                     //printf("$$ Existing member %s %s add scope %s\n",
2807                     //    dstMi->ambiguityResolutionScope.data(),
2808                     //    dstMd->name().data(),
2809                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
2810
2811                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
2812                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
2813                       dstMi->ambiguityResolutionScope.prepend(scope);
2814                     ambigue=TRUE;
2815                   }
2816                 }
2817                 else // same members
2818                 {
2819                   // do not add if base class is virtual or
2820                   // if scope paths are equal or
2821                   // if base class is an interface (and thus implicitly virtual).
2822                   //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt);
2823                   if ((srcMi->virt!=Normal && dstMi->virt!=Normal) ||
2824                       bClass->name()+sep+srcMi->scopePath == dstMi->scopePath ||
2825                       dstMd->getClassDef()->compoundType()==Interface
2826                      )
2827                   {
2828                     found=TRUE;
2829                   }
2830                   else // member can be reached via multiple paths in the
2831                     // inheritance tree
2832                   {
2833                     //printf("$$ Existing member %s %s add scope %s\n",
2834                     //    dstMi->ambiguityResolutionScope.data(),
2835                     //    dstMd->name().data(),
2836                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
2837
2838                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
2839                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
2840                     {
2841                       dstMi->ambiguityResolutionScope.prepend(scope);
2842                     }
2843                     ambigue=TRUE;
2844                   }
2845                 }
2846               }
2847               //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n",
2848               //    srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass);
2849
2850               // TODO: fix the case where a member is hidden by inheritance
2851               //       of a member with the same name but with another prototype,
2852               //       while there is more than one path to the member in the
2853               //       base class due to multiple inheritance. In this case
2854               //       it seems that the member is not reachable by prefixing a
2855               //       scope name either (according to my compiler). Currently,
2856               //       this case is shown anyway.
2857               if (!found && srcMd->protection()!=Private && !srcMd->isFriend())
2858               {
2859                 Protection prot=srcMd->protection();
2860                 if (bcd->prot==Protected && prot==Public)       prot=bcd->prot;
2861                 else if (bcd->prot==Private)                    prot=bcd->prot;
2862
2863                 if (inlineInheritedMembers)
2864                 {
2865                   if (!isStandardFunc(srcMd))
2866                   {
2867                     //printf("    insertMember `%s'\n",srcMd->name().data());
2868                     internalInsertMember(srcMd,prot,FALSE);
2869                   }
2870                 }
2871
2872                 Specifier virt=srcMi->virt;
2873                 if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
2874
2875                 MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE);
2876                 newMi->scopePath=bClass->name()+sep+srcMi->scopePath;
2877                 if (ambigue)
2878                 {
2879                   //printf("$$ New member %s %s add scope %s::\n",
2880                   //     srcMi->ambiguityResolutionScope.data(),
2881                   //     srcMd->name().data(),
2882                   //     bClass->name().data());
2883
2884                   QCString scope=bClass->name()+sep;
2885                   if (scope!=srcMi->ambiguityResolutionScope.left(scope.length()))
2886                   {
2887                     newMi->ambiguityResolutionScope=
2888                       scope+srcMi->ambiguityResolutionScope.copy();
2889                   }
2890                 }
2891                 if (hidden)
2892                 {
2893                   if (srcMi->ambigClass==0)
2894                   {
2895                     newMi->ambigClass=bClass;
2896                     newMi->ambiguityResolutionScope=bClass->name()+sep;
2897                   }
2898                   else
2899                   {
2900                     newMi->ambigClass=srcMi->ambigClass;
2901                     newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep;
2902                   }
2903                 }
2904                 dstMni->append(newMi);
2905               }
2906             }
2907           }
2908           else // base class has a member that is not in the sub class => copy
2909           {
2910             // create a deep copy of the list (only the MemberInfo's will be
2911             // copied, not the actual MemberDef's)
2912             MemberNameInfo *newMni = 0;
2913             newMni = new MemberNameInfo(srcMni->memberName());
2914
2915             // copy the member(s) from the base to the sub class
2916             MemberNameInfoIterator mnii(*srcMni);
2917             MemberInfo *mi;
2918             for (;(mi=mnii.current());++mnii)
2919             {
2920               if (!mi->memberDef->isFriend()) // don't inherit friends
2921               {
2922                 Protection prot = mi->prot;
2923                 if (bcd->prot==Protected)
2924                 {
2925                   if (prot==Public) prot=Protected;
2926                 }
2927                 else if (bcd->prot==Private)
2928                 {
2929                   prot=Private;
2930                 }
2931                 //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n",
2932                 //    name().data(),mi->memberDef->name().data(),mi->prot,
2933                 //    bcd->prot,prot);
2934
2935                 if (mi->prot!=Private)
2936                 {
2937                   Specifier virt=mi->virt;
2938                   if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
2939
2940                   if (inlineInheritedMembers)
2941                   {
2942                     if (!isStandardFunc(mi->memberDef))
2943                     {
2944                       //printf("    insertMember `%s'\n",mi->memberDef->name().data());
2945                       internalInsertMember(mi->memberDef,prot,FALSE);
2946                     }
2947                   }
2948                   //printf("Adding!\n");
2949                   MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE);
2950                   newMi->scopePath=bClass->name()+sep+mi->scopePath;
2951                   newMi->ambigClass=mi->ambigClass;
2952                   newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
2953                   newMni->append(newMi);
2954                 }
2955               }
2956             }
2957
2958             if (dstMnd==0)
2959             {
2960               m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
2961               m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
2962               dstMnd = m_impl->allMemberNameInfoSDict;
2963             }
2964             // add it to the dictionary
2965             dstMnd->append(newMni->memberName(),newMni);
2966           }
2967         }
2968       }
2969     }
2970   }
2971   //printf("  end mergeMembers\n");
2972 }
2973
2974 //----------------------------------------------------------------------------
2975
2976 /*! Merges the members of a Objective-C category into this class.
2977  */
2978 void ClassDef::mergeCategory(ClassDef *category)
2979 {
2980   static bool extractLocalMethods = Config_getBool("EXTRACT_LOCAL_METHODS");
2981   bool makePrivate = category->isLocal();
2982   // in case extract local methods is not enabled we don't add the methods
2983   // of the category in case it is defined in the .m file.
2984   if (makePrivate && !extractLocalMethods) return;
2985   bool isExtension = category->isExtension();
2986
2987   category->setCategoryOf(this);
2988   if (isExtension)
2989   {
2990     category->setArtificial(TRUE);
2991
2992     // copy base classes/protocols from extension
2993     if (category->baseClasses())
2994     {
2995       BaseClassListIterator bcli(*category->baseClasses());
2996       BaseClassDef *bcd;
2997       for ( ; (bcd=bcli.current()) ; ++bcli )
2998       {
2999         insertBaseClass(bcd->classDef,bcd->usedName,bcd->prot,bcd->virt,bcd->templSpecifiers);
3000         // correct bcd->classDef so that they do no longer derive from
3001         // category, but from this class!
3002         if (bcd->classDef->subClasses())
3003         {
3004           BaseClassListIterator scli(*bcd->classDef->subClasses());
3005           BaseClassDef *scd;
3006           for ( ; (scd=scli.current()) ; ++scli )
3007           {
3008             if (scd->classDef==category)
3009             {
3010               scd->classDef=this;
3011             }
3012           }
3013         }
3014       }
3015     }
3016
3017   }
3018   // make methods private for categories defined in the .m file
3019   //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate);
3020
3021   MemberNameInfoSDict *srcMnd  = category->memberNameInfoSDict();
3022   MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
3023
3024   if (srcMnd && dstMnd)
3025   {
3026     MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
3027     MemberNameInfo *srcMni;
3028     for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
3029     {
3030       MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName());
3031       if (dstMni) // method is already defined in the class
3032       {
3033         //printf("Existing member %s\n",srcMni->memberName());
3034         MemberInfo *dstMi = dstMni->getFirst();
3035         MemberInfo *srcMi = srcMni->getFirst();
3036         //if (dstMi)
3037         //{
3038         //  Protection prot = dstMi->prot;
3039         //  if (makePrivate || isExtension)
3040         //  {
3041         //    prot = Private;
3042         //    removeMemberFromLists(dstMi->memberDef);
3043         //    internalInsertMember(dstMi->memberDef,prot,FALSE);
3044         //  }
3045         //}
3046         if (srcMi && dstMi)
3047         {
3048           combineDeclarationAndDefinition(srcMi->memberDef,dstMi->memberDef);
3049           dstMi->memberDef->setCategory(category);
3050           dstMi->memberDef->setCategoryRelation(srcMi->memberDef);
3051           srcMi->memberDef->setCategoryRelation(dstMi->memberDef);
3052         }
3053       }
3054       else // new method name
3055       {
3056         //printf("New member %s\n",srcMni->memberName());
3057         // create a deep copy of the list
3058         MemberNameInfo *newMni = 0;
3059         newMni = new MemberNameInfo(srcMni->memberName());
3060
3061         // copy the member(s) from the category to this class
3062         MemberNameInfoIterator mnii(*srcMni);
3063         MemberInfo *mi;
3064         for (;(mi=mnii.current());++mnii)
3065         {
3066           //printf("Adding '%s'\n",mi->memberDef->name().data());
3067           Protection prot = mi->prot;
3068           //if (makePrivate) prot = Private;
3069           MemberDef *newMd = mi->memberDef->deepCopy();
3070           //printf("Copying member %s\n",mi->memberDef->name().data());
3071           newMd->moveTo(this);
3072
3073           MemberInfo *newMi=new MemberInfo(newMd,prot,mi->virt,mi->inherited);
3074           newMi->scopePath=mi->scopePath;
3075           newMi->ambigClass=mi->ambigClass;
3076           newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope;
3077           newMni->append(newMi);
3078
3079           // also add the newly created member to the global members list
3080           if (newMd)
3081           {
3082             MemberName *mn;
3083             QCString name = newMd->name();
3084             if ((mn=Doxygen::memberNameSDict->find(name)))
3085             {
3086               mn->append(newMd);
3087             }
3088             else
3089             {
3090               mn = new MemberName(newMd->name());
3091               mn->append(newMd);
3092               Doxygen::memberNameSDict->append(name,mn);
3093             }
3094           }
3095
3096           newMd->setCategory(category);
3097           newMd->setCategoryRelation(mi->memberDef);
3098           mi->memberDef->setCategoryRelation(newMd);
3099           if (makePrivate || isExtension)
3100           {
3101             newMd->makeImplementationDetail();
3102           }
3103           internalInsertMember(newMd,prot,FALSE);
3104         }
3105
3106         // add it to the dictionary
3107         dstMnd->append(newMni->memberName(),newMni);
3108       }
3109     }
3110   }
3111 }
3112
3113 //----------------------------------------------------------------------------
3114
3115 void ClassDef::addUsedClass(ClassDef *cd,const char *accessName,
3116                Protection prot)
3117 {
3118   static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
3119   static bool umlLook = Config_getBool("UML_LOOK");
3120   if (prot==Private && !extractPrivate) return;
3121   //printf("%s::addUsedClass(%s,%s)\n",name().data(),cd->name().data(),accessName);
3122   if (m_impl->usesImplClassDict==0)
3123   {
3124     m_impl->usesImplClassDict = new UsesClassDict(17);
3125     m_impl->usesImplClassDict->setAutoDelete(TRUE);
3126   }
3127   UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
3128   if (ucd==0)
3129   {
3130      ucd = new UsesClassDef(cd);
3131      m_impl->usesImplClassDict->insert(cd->name(),ucd);
3132      //printf("Adding used class %s to class %s via accessor %s\n",
3133      //    cd->name().data(),name().data(),accessName);
3134   }
3135   QCString acc = accessName;
3136   if (umlLook)
3137   {
3138     switch(prot)
3139     {
3140       case Public:    acc.prepend("+"); break;
3141       case Private:   acc.prepend("-"); break;
3142       case Protected: acc.prepend("#"); break;
3143       case Package:   acc.prepend("~"); break;
3144     }
3145   }
3146   ucd->addAccessor(acc);
3147 }
3148
3149 void ClassDef::addUsedByClass(ClassDef *cd,const char *accessName,
3150                Protection prot)
3151 {
3152   static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
3153   static bool umlLook = Config_getBool("UML_LOOK");
3154   if (prot==Private && !extractPrivate) return;
3155   //printf("%s::addUsedByClass(%s,%s)\n",name().data(),cd->name().data(),accessName);
3156   if (m_impl->usedByImplClassDict==0)
3157   {
3158     m_impl->usedByImplClassDict = new UsesClassDict(17);
3159     m_impl->usedByImplClassDict->setAutoDelete(TRUE);
3160   }
3161   UsesClassDef *ucd=m_impl->usedByImplClassDict->find(cd->name());
3162   if (ucd==0)
3163   {
3164      ucd = new UsesClassDef(cd);
3165      m_impl->usedByImplClassDict->insert(cd->name(),ucd);
3166      //printf("Adding used by class %s to class %s\n",
3167      //    cd->name().data(),name().data());
3168   }
3169   QCString acc = accessName;
3170   if (umlLook)
3171   {
3172     switch(prot)
3173     {
3174       case Public:    acc.prepend("+"); break;
3175       case Private:   acc.prepend("-"); break;
3176       case Protected: acc.prepend("#"); break;
3177       case Package:   acc.prepend("~"); break;
3178     }
3179   }
3180   ucd->addAccessor(acc);
3181 }
3182
3183
3184 #if 0
3185 /*! Builds up a dictionary of all classes that are used by the state of this
3186  *  class (the "implementation").
3187  *  Must be called before mergeMembers() is called!
3188  */
3189
3190 void ClassDef::determineImplUsageRelation()
3191 {
3192   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
3193   MemberNameInfo *mni;
3194   for (;(mni=mnili.current());++mnili)
3195   {
3196     MemberNameInfoIterator mnii(*mni);
3197     MemberInfo *mi;
3198     for (mnii.toFirst();(mi=mnii.current());++mnii)
3199     {
3200       MemberDef *md=mi->memberDef;
3201       if (md->isVariable()) // for each member variable in this class
3202       {
3203         QCString type=removeRedundantWhiteSpace(md->typeString());
3204         //printf("in class %s found var type=`%s' name=`%s'\n",
3205         //            name().data(),type.data(),md->name().data());
3206         int pos=0;
3207         QCString usedClassName;
3208         QCString templSpec;
3209         bool found=FALSE;
3210         while (extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1 && !found)
3211         {
3212           //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data());
3213           // check if usedClassName is a template argument of its class
3214           ClassDef *cd=md->getClassDef();
3215           if (cd && cd->templateArguments())
3216           {
3217             ArgumentListIterator ali(*cd->templateArguments());
3218             Argument *arg;
3219             int count=0;
3220             for (ali.toFirst();(arg=ali.current());++ali,++count)
3221             {
3222               if (arg->name==usedClassName) // type is a template argument
3223               {
3224                 found=TRUE;
3225                 if (m_impl->usesImplClassDict==0) m_impl->usesImplClassDict = new UsesClassDict(257);
3226                 cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(),
3227                     usedClassName,ClassDef::Class);
3228                 cd->setIsTemplateBaseClass(count);
3229                 UsesClassDef *ucd = new UsesClassDef(cd);
3230                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
3231                 ucd->templSpecifiers = templSpec;
3232                 ucd->addAccessor(md->name());
3233                 Doxygen::hiddenClasses.append(cd);
3234                 //printf("Adding used template argument %s to class %s\n",
3235                 //    cd->name().data(),name().data());
3236                 //printf("Adding accessor %s to class %s\n",
3237                 //    md->name().data(),ucd->classDef->name().data());
3238               }
3239             }
3240           }
3241
3242           if (!found)
3243           {
3244             cd=0;
3245             if (getNamespaceDef()!=0)
3246             {
3247               cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec);
3248             }
3249             if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec);
3250             if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try in-between scopes!
3251             //printf("Search for class %s result=%p\n",usedClassName.data(),cd);
3252             if (cd) // class exists
3253             {
3254               found=TRUE;
3255               if (m_impl->usesImplClassDict==0)
3256               {
3257                 m_impl->usesImplClassDict = new UsesClassDict(257);
3258                 m_impl->usesImplClassDict->setAutoDelete(TRUE);
3259               }
3260               UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
3261               if (ucd==0 || ucd->templSpecifiers!=templSpec)
3262               {
3263                 ucd = new UsesClassDef(cd);
3264                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
3265                 ucd->templSpecifiers = templSpec;
3266                 //printf("Adding used class %s to class %s\n",
3267                 //    cd->name().data(),name().data());
3268               }
3269               ucd->addAccessor(md->name());
3270               //printf("Adding accessor %s to class %s\n",
3271               //    md->name().data(),ucd->classDef->name().data());
3272             }
3273           }
3274         }
3275       }
3276     }
3277   }
3278 #ifdef DUMP
3279   if (m_impl->usesClassDict)
3280   {
3281     msg("Class %s uses the following classes:\n",name().data());
3282     UsesClassDictIterator ucdi(*m_impl->usesClassDict);
3283     UsesClassDef *ucd;
3284     for (;(ucd=ucdi.current());++ucdi)
3285     {
3286       msg("  %s via ",ucd->classDef->name().data());
3287       QDictIterator<void> dvi(*ucd->accessors);
3288       const char *s;
3289       for (;(s=dvi.currentKey());++dvi)
3290       {
3291         msg("%s ",s);
3292       }
3293       msg("\n");
3294     }
3295   }
3296 #endif
3297 }
3298
3299 //----------------------------------------------------------------------------
3300
3301 // I have disabled this code because the graphs it renders quickly become
3302 // too large to be of practical use.
3303
3304 void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr)
3305 {
3306   QCString type = typeStr;
3307   static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
3308   int p=0,i,l;
3309   while ((i=re.match(type,p,&l))!=-1) // for each class name in the type
3310   {
3311     ClassDef *cd=getClass(name()+"::"+type.mid(i,l));
3312     if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try in-between scopes!
3313     if (cd && cd!=this && !isBaseClass(cd))
3314     {
3315       if (m_impl->usesIntfClassDict==0)
3316       {
3317         m_impl->usesIntfClassDict = new UsesClassDict(257);
3318       }
3319       UsesClassDef *ucd=m_impl->usesIntfClassDict->find(cd->name());
3320       if (ucd==0)
3321       {
3322         ucd = new UsesClassDef(cd);
3323         m_impl->usesIntfClassDict->insert(cd->name(),ucd);
3324         //printf("in class `%s' adding used intf class `%s'\n",
3325         //  name().data(),cd->name().data());
3326       }
3327       ucd->addAccessor(md->name());
3328       //printf("in class `%s' adding accessor `%s' to class `%s'\n",
3329       //    name().data(),md->name().data(),ucd->classDef->name().data());
3330     }
3331     p=i+l;
3332   }
3333 }
3334
3335 void ClassDef::determineIntfUsageRelation()
3336 {
3337   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoList);
3338   MemberNameInfo *mni;
3339   for (;(mni=mnili.current());++mnili)
3340   {
3341     MemberNameInfoIterator mnii(*mni);
3342     MemberInfo *mi;
3343     for (mnii.toFirst();(mi=mnii.current());++mnii)
3344     {
3345       MemberDef *md=mi->memberDef;
3346
3347       // compute the protection level for this member
3348       Protection protect=md->protection();
3349       if (mi->prot==Protected) // inherited protection
3350       {
3351         if (protect==Public) protect=Protected;
3352         else if (protect==Protected) protect=Private;
3353       }
3354
3355       if (!md->name().isEmpty() && md->name()[0]!='@' &&
3356           (mi->prot!=Private && protect!=Private)
3357          )
3358       {
3359         // add classes found in the return type
3360         addUsedInterfaceClasses(md,md->typeString());
3361         ArgumentList *al = md->argumentList();
3362         if (al) // member has arguments
3363         {
3364           // add classes found in the types of the argument list
3365           ArgumentListIterator ali(*al);
3366           Argument *a;
3367           for (;(a=ali.current());++ali)
3368           {
3369             if (!a->type.isEmpty() && a->type.at(0)!='@')
3370             {
3371               addUsedInterfaceClasses(md,a->type);
3372             }
3373           }
3374         }
3375       }
3376     }
3377   }
3378 }
3379 #endif
3380
3381 QCString ClassDef::compoundTypeString() const
3382 {
3383   if (getLanguage()==SrcLangExt_Fortran)
3384   {
3385     switch (m_impl->compType)
3386     {
3387       case Class:     return "module";
3388       case Struct:    return "type";
3389       case Union:     return "union";
3390       case Interface: return "interface";
3391       case Protocol:  return "protocol";
3392       case Category:  return "category";
3393       case Exception: return "exception";
3394       default:        return "unknown";
3395     }
3396   }
3397   else
3398   {
3399     switch (m_impl->compType)
3400     {
3401       case Class:     return isJavaEnum() ? "enum" : "class";
3402       case Struct:    return "struct";
3403       case Union:     return "union";
3404       case Interface: return getLanguage()==SrcLangExt_ObjC ? "class" : "interface";
3405       case Protocol:  return "protocol";
3406       case Category:  return "category";
3407       case Exception: return "exception";
3408       case Service:   return "service";
3409       case Singleton: return "singleton";
3410       default:        return "unknown";
3411     }
3412   }
3413 }
3414
3415 QCString ClassDef::getOutputFileBase() const
3416 {
3417   static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES");
3418   static bool inlineSimpleClasses = Config_getBool("INLINE_SIMPLE_STRUCTS");
3419   if (!Doxygen::generatingXmlOutput)
3420   {
3421     Definition *scope=0;
3422     if (inlineGroupedClasses && partOfGroups()!=0)
3423     {
3424       // point to the group that embeds this class
3425       return partOfGroups()->at(0)->getOutputFileBase();
3426     }
3427     else if (inlineSimpleClasses && m_impl->isSimple && partOfGroups()!=0)
3428     {
3429       // point to simple struct inside a group
3430       return partOfGroups()->at(0)->getOutputFileBase();
3431     }
3432     else if (inlineSimpleClasses && m_impl->isSimple && (scope=getOuterScope()))
3433     {
3434       if (scope==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) // simple struct embedded in file
3435       {
3436         return getFileDef()->getOutputFileBase();
3437       }
3438       else if (scope->isLinkableInProject()) // simple struct embedded in other container (namespace/group/class)
3439       {
3440         return getOuterScope()->getOutputFileBase();
3441       }
3442     }
3443   }
3444   if (m_impl->templateMaster)
3445   {
3446     // point to the template of which this class is an instance
3447     return m_impl->templateMaster->getOutputFileBase();
3448   }
3449   else if (isReference())
3450   {
3451     // point to the external location
3452     return m_impl->fileName;
3453   }
3454   else
3455   {
3456     // normal locally defined class
3457     return convertNameToFile(m_impl->fileName);
3458   }
3459 }
3460
3461 QCString ClassDef::getInstanceOutputFileBase() const
3462 {
3463   if (isReference())
3464   {
3465     return m_impl->fileName;
3466   }
3467   else
3468   {
3469     return convertNameToFile(m_impl->fileName);
3470   }
3471 }
3472
3473 QCString ClassDef::getFileBase() const
3474 {
3475   if (m_impl->templateMaster)
3476   {
3477     return m_impl->templateMaster->getFileBase();
3478   }
3479   else
3480   {
3481     return m_impl->fileName;
3482   }
3483 }
3484
3485 QCString ClassDef::getSourceFileBase() const
3486 {
3487   if (m_impl->templateMaster)
3488   {
3489     return m_impl->templateMaster->getSourceFileBase();
3490   }
3491   else
3492   {
3493     return Definition::getSourceFileBase();
3494   }
3495 }
3496
3497 void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs)
3498 {
3499   gd->addClass(this);
3500   //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data());
3501   if (m_impl->allMemberNameInfoSDict==0) return;
3502   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
3503   MemberNameInfo *mni;
3504   for (;(mni=mnili.current());++mnili)
3505   {
3506     MemberNameInfoIterator mnii(*mni);
3507     MemberInfo *mi;
3508     for (mnii.toFirst();(mi=mnii.current());++mnii)
3509     {
3510       MemberDef *md=mi->memberDef;
3511       md->setGroupDef(gd,pri,fileName,startLine,hasDocs);
3512       gd->insertMember(md,TRUE);
3513       ClassDef *innerClass = md->getClassDefOfAnonymousType();
3514       if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs);
3515     }
3516   }
3517 }
3518
3519 void ClassDef::addInnerCompound(Definition *d)
3520 {
3521   //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data());
3522   if (d->definitionType()==Definition::TypeClass) // only classes can be
3523                                                   // nested in classes.
3524   {
3525     if (m_impl->innerClasses==0)
3526     {
3527       m_impl->innerClasses = new ClassSDict(17);
3528     }
3529     m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d);
3530   }
3531 }
3532
3533 Definition *ClassDef::findInnerCompound(const char *name)
3534 {
3535   Definition *result=0;
3536   if (name==0) return 0;
3537   if (m_impl->innerClasses)
3538   {
3539     result = m_impl->innerClasses->find(name);
3540   }
3541   return result;
3542 }
3543
3544 //void ClassDef::initTemplateMapping()
3545 //{
3546 //  m_impl->templateMapping->clear();
3547 //  ArgumentList *al = templateArguments();
3548 //  if (al)
3549 //  {
3550 //    ArgumentListIterator ali(*al);
3551 //    Argument *arg;
3552 //    for (ali.toFirst();(arg=ali.current());++ali)
3553 //    {
3554 //      setTemplateArgumentMapping(arg->name,arg->defval);
3555 //    }
3556 //  }
3557 //}
3558 //void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual)
3559 //{
3560 //  //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual);
3561 //  if (m_impl->templateMapping && formal)
3562 //  {
3563 //    if (m_impl->templateMapping->find(formal))
3564 //    {
3565 //      m_impl->templateMapping->remove(formal);
3566 //    }
3567 //    m_impl->templateMapping->insert(formal,new QCString(actual));
3568 //  }
3569 //}
3570 //
3571 //QCString ClassDef::getTemplateArgumentMapping(const char *formal) const
3572 //{
3573 //  if (m_impl->templateMapping && formal)
3574 //  {
3575 //    QCString *s = m_impl->templateMapping->find(formal);
3576 //    if (s)
3577 //    {
3578 //      return *s;
3579 //    }
3580 //  }
3581 //  return "";
3582 //}
3583
3584 ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName,
3585     int startLine, int startColumn, const QCString &templSpec,bool &freshInstance)
3586 {
3587   freshInstance = FALSE;
3588   if (m_impl->templateInstances==0)
3589   {
3590     m_impl->templateInstances = new QDict<ClassDef>(17);
3591   }
3592   ClassDef *templateClass=m_impl->templateInstances->find(templSpec);
3593   if (templateClass==0)
3594   {
3595     Debug::print(Debug::Classes,0,"      New template instance class `%s'`%s'\n",name().data(),templSpec.data());
3596     QCString tcname = removeRedundantWhiteSpace(localName()+templSpec);
3597     templateClass = new ClassDef(
3598         fileName,startLine,startColumn,tcname,ClassDef::Class);
3599     templateClass->setTemplateMaster(this);
3600     templateClass->setOuterScope(getOuterScope());
3601     templateClass->setHidden(isHidden());
3602     m_impl->templateInstances->insert(templSpec,templateClass);
3603     freshInstance=TRUE;
3604   }
3605   return templateClass;
3606 }
3607
3608 ClassDef *ClassDef::getVariableInstance(const char *templSpec)
3609 {
3610   if (m_impl->variableInstances==0)
3611   {
3612     m_impl->variableInstances = new QDict<ClassDef>(17);
3613     m_impl->variableInstances->setAutoDelete(TRUE);
3614   }
3615   ClassDef *templateClass=m_impl->variableInstances->find(templSpec);
3616   if (templateClass==0)
3617   {
3618     Debug::print(Debug::Classes,0,"      New template variable instance class `%s'`%s'\n",qPrint(name()),qPrint(templSpec));
3619     QCString tcname = removeRedundantWhiteSpace(name()+templSpec);
3620     templateClass = new ClassDef("<code>",1,1,tcname,
3621                         ClassDef::Class,0,0,FALSE);
3622     templateClass->addMembersToTemplateInstance( this, templSpec );
3623     templateClass->setTemplateMaster(this);
3624     m_impl->variableInstances->insert(templSpec,templateClass);
3625   }
3626   return templateClass;
3627 }
3628
3629 void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames)
3630 {
3631   if (templateNames==0) return;
3632   if (m_impl->templBaseClassNames==0)
3633   {
3634     m_impl->templBaseClassNames = new QDict<int>(17);
3635     m_impl->templBaseClassNames->setAutoDelete(TRUE);
3636   }
3637   // make a deep copy of the dictionary.
3638   QDictIterator<int> qdi(*templateNames);
3639   for (;qdi.current();++qdi)
3640   {
3641     if (m_impl->templBaseClassNames->find(qdi.currentKey())==0)
3642     {
3643       m_impl->templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current()));
3644     }
3645   }
3646 }
3647
3648 QDict<int> *ClassDef::getTemplateBaseClassNames() const
3649 {
3650   return m_impl->templBaseClassNames;
3651 }
3652
3653 void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec)
3654 {
3655   //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec);
3656   if (cd->memberNameInfoSDict()==0) return;
3657   MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict());
3658   MemberNameInfo *mni;
3659   for (;(mni=mnili.current());++mnili)
3660   {
3661     MemberNameInfoIterator mnii(*mni);
3662     MemberInfo *mi;
3663     for (mnii.toFirst();(mi=mnii.current());++mnii)
3664     {
3665       ArgumentList *actualArguments = new ArgumentList;
3666       stringToArgumentList(templSpec,actualArguments);
3667       MemberDef *md = mi->memberDef;
3668       MemberDef *imd = md->createTemplateInstanceMember(
3669                           cd->templateArguments(),actualArguments);
3670       delete actualArguments;
3671       //printf("%s->setMemberClass(%p)\n",imd->name().data(),this);
3672       imd->setMemberClass(this);
3673       imd->setTemplateMaster(md);
3674       imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
3675       imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
3676       imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
3677       imd->setMemberSpecifiers(md->getMemberSpecifiers());
3678       imd->setMemberGroupId(md->getMemberGroupId());
3679       insertMember(imd);
3680       //printf("Adding member=%s %s%s to class %s templSpec %s\n",
3681       //    imd->typeString(),imd->name().data(),imd->argsString(),
3682       //    imd->getClassDef()->name().data(),templSpec);
3683       // insert imd in the list of all members
3684       //printf("Adding member=%s class=%s\n",imd->name().data(),name().data());
3685       MemberName *mn = Doxygen::memberNameSDict->find(imd->name());
3686       if (mn==0)
3687       {
3688         mn = new MemberName(imd->name());
3689         Doxygen::memberNameSDict->append(imd->name(),mn);
3690       }
3691       mn->append(imd);
3692     }
3693   }
3694 }
3695
3696 QCString ClassDef::getReference() const
3697 {
3698   if (m_impl->templateMaster)
3699   {
3700     return m_impl->templateMaster->getReference();
3701   }
3702   else
3703   {
3704     return Definition::getReference();
3705   }
3706 }
3707
3708 bool ClassDef::isReference() const
3709 {
3710   if (m_impl->templateMaster)
3711   {
3712     return m_impl->templateMaster->isReference();
3713   }
3714   else
3715   {
3716     return Definition::isReference();
3717   }
3718 }
3719
3720 void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const
3721 {
3722   Definition *d=getOuterScope();
3723   if (d)
3724   {
3725     if (d->definitionType()==Definition::TypeClass)
3726     {
3727       ClassDef *cd=(ClassDef *)d;
3728       cd->getTemplateParameterLists(lists);
3729     }
3730   }
3731   if (templateArguments())
3732   {
3733     lists.append(templateArguments());
3734   }
3735 }
3736
3737 QCString ClassDef::qualifiedNameWithTemplateParameters(
3738     QList<ArgumentList> *actualParams,int *actualParamIndex) const
3739 {
3740   //static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
3741   static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES");
3742   //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data());
3743   QCString scName;
3744   Definition *d=getOuterScope();
3745   if (d)
3746   {
3747     if (d->definitionType()==Definition::TypeClass)
3748     {
3749       ClassDef *cd=(ClassDef *)d;
3750       scName = cd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex);
3751     }
3752     else if (!hideScopeNames)
3753     {
3754       scName = d->qualifiedName();
3755     }
3756   }
3757
3758   SrcLangExt lang = getLanguage();
3759   QCString scopeSeparator = getLanguageSpecificSeparator(lang);
3760   if (!scName.isEmpty()) scName+=scopeSeparator;
3761
3762   bool isSpecialization = localName().find('<')!=-1;
3763
3764   QCString clName = className();
3765   //bool isGeneric = getLanguage()==SrcLangExt_CSharp;
3766   //if (isGeneric && clName.right(2)=="-g")
3767   //{
3768   //  clName = clName.left(clName.length()-2);
3769   //}
3770   //printf("m_impl->lang=%d clName=%s\n",m_impl->lang,clName.data());
3771   scName+=clName;
3772   ArgumentList *al=0;
3773   if (templateArguments())
3774   {
3775     if (actualParams && *actualParamIndex<(int)actualParams->count())
3776     {
3777       al = actualParams->at(*actualParamIndex);
3778       if (!isSpecialization)
3779       {
3780         scName+=tempArgListToString(al);
3781       }
3782       (*actualParamIndex)++;
3783     }
3784     else
3785     {
3786       if (!isSpecialization)
3787       {
3788         scName+=tempArgListToString(templateArguments());
3789       }
3790     }
3791   }
3792   //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data());
3793   return scName;
3794 }
3795
3796 QCString ClassDef::className() const
3797 {
3798   if (m_impl->className.isEmpty())
3799   {
3800     return localName();
3801   }
3802   else
3803   {
3804     return m_impl->className;
3805   }
3806 };
3807
3808 void ClassDef::setClassName(const char *name)
3809 {
3810   m_impl->className = name;
3811 }
3812
3813 void ClassDef::addListReferences()
3814 {
3815   SrcLangExt lang = getLanguage();
3816   if (!isLinkableInProject()) return;
3817   //printf("ClassDef(%s)::addListReferences()\n",name().data());
3818   {
3819     QList<ListItemInfo> *xrefItems = xrefListItems();
3820     addRefItem(xrefItems,
3821              qualifiedName(),
3822              lang==SrcLangExt_Fortran ? theTranslator->trType(TRUE,TRUE)
3823                                       : theTranslator->trClass(TRUE,TRUE),
3824              getOutputFileBase(),
3825              displayName(),
3826              0
3827             );
3828   }
3829   if (m_impl->memberGroupSDict)
3830   {
3831     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
3832     MemberGroup *mg;
3833     for (;(mg=mgli.current());++mgli)
3834     {
3835       mg->addListReferences(this);
3836     }
3837   }
3838   QListIterator<MemberList> mli(m_impl->memberLists);
3839   MemberList *ml;
3840   for (mli.toFirst();(ml=mli.current());++mli)
3841   {
3842     if (ml->listType()&MemberListType_detailedLists)
3843     {
3844       ml->addListReferences(this);
3845     }
3846   }
3847 }
3848
3849 MemberDef *ClassDef::getMemberByName(const QCString &name) const
3850 {
3851   MemberDef *xmd = 0;
3852   if (m_impl->allMemberNameInfoSDict)
3853   {
3854     MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name);
3855     if (mni)
3856     {
3857       const int maxInheritanceDepth = 100000;
3858       int mdist=maxInheritanceDepth;
3859       MemberNameInfoIterator mnii(*mni);
3860       MemberInfo *mi;
3861       for (mnii.toFirst();(mi=mnii.current());++mnii)
3862       {
3863         ClassDef *mcd=mi->memberDef->getClassDef();
3864         int m=minClassDistance(this,mcd);
3865         //printf("found member in %s linkable=%d m=%d\n",
3866         //    mcd->name().data(),mcd->isLinkable(),m);
3867         if (m<mdist && mcd->isLinkable())
3868         {
3869           mdist=m;
3870           xmd=mi->memberDef;
3871         }
3872       }
3873     }
3874   }
3875   //printf("getMemberByName(%s)=%p\n",name.data(),xmd);
3876   return xmd;
3877 }
3878
3879 bool ClassDef::isAccessibleMember(MemberDef *md)
3880 {
3881   return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE);
3882 }
3883
3884 MemberList *ClassDef::createMemberList(MemberListType lt)
3885 {
3886   m_impl->memberLists.setAutoDelete(TRUE);
3887   QListIterator<MemberList> mli(m_impl->memberLists);
3888   MemberList *ml;
3889   for (mli.toFirst();(ml=mli.current());++mli)
3890   {
3891     if (ml->listType()==lt)
3892     {
3893       return ml;
3894     }
3895   }
3896   // not found, create a new member list
3897   ml = new MemberList(lt);
3898   m_impl->memberLists.append(ml);
3899   return ml;
3900 }
3901
3902 MemberList *ClassDef::getMemberList(MemberListType lt)
3903 {
3904   QListIterator<MemberList> mli(m_impl->memberLists);
3905   MemberList *ml;
3906   for (;(ml=mli.current());++mli)
3907   {
3908     if (ml->listType()==lt)
3909     {
3910       return ml;
3911     }
3912   }
3913   return 0;
3914 }
3915
3916 void ClassDef::addMemberToList(MemberListType lt,MemberDef *md,bool isBrief)
3917 {
3918   static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
3919   static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
3920   MemberList *ml = createMemberList(lt);
3921   ml->setNeedsSorting((isBrief && sortBriefDocs) || (!isBrief && sortMemberDocs));
3922   ml->append(md);
3923
3924   // for members in the declaration lists we set the section, needed for member grouping
3925   if ((ml->listType()&MemberListType_detailedLists)==0) md->setSectionList(this,ml);
3926 }
3927
3928 void ClassDef::sortMemberLists()
3929 {
3930   QListIterator<MemberList> mli(m_impl->memberLists);
3931   MemberList *ml;
3932   for (;(ml=mli.current());++mli)
3933   {
3934     if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
3935   }
3936   if (m_impl->innerClasses)
3937   {
3938     m_impl->innerClasses->sort();
3939   }
3940 }
3941
3942 int ClassDef::countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom,
3943                                       int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses)
3944 {
3945   //printf("%s: countMemberDeclarations for %d and %d\n",name().data(),lt,lt2);
3946   int count=0;
3947   MemberList * ml  = getMemberList(lt);
3948   MemberList * ml2 = getMemberList((MemberListType)lt2);
3949   if (getLanguage()!=SrcLangExt_VHDL) // use specific declarations function
3950   {
3951     if (ml)
3952     {
3953       ml->countDecMembers();
3954       count+=ml->numDecMembers();
3955       //printf("-> ml=%d\n",ml->numDecMembers());
3956     }
3957     if (ml2)
3958     {
3959       ml2->countDecMembers();
3960       count+=ml2->numDecMembers();
3961       //printf("-> ml2=%d\n",ml2->numDecMembers());
3962     }
3963     // also include grouped members that have their own section in the class (see bug 722759)
3964     if (inheritedFrom && m_impl->memberGroupSDict)
3965     {
3966       MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
3967       MemberGroup *mg;
3968       for (;(mg=mgli.current());++mgli)
3969       {
3970         count+=mg->countGroupedInheritedMembers(lt);
3971         if (lt2!=1) count+=mg->countGroupedInheritedMembers((MemberListType)lt2);
3972       }
3973     }
3974     static bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB");
3975     if (!inlineInheritedMembers) // show inherited members as separate lists
3976     {
3977       QPtrDict<void> visited(17);
3978       count+=countInheritedDecMembers(lt,inheritedFrom,invert,showAlways,visitedClasses);
3979     }
3980   }
3981   //printf("-> %d\n",count);
3982   return count;
3983 }
3984
3985
3986 int ClassDef::countInheritedDecMembers(MemberListType lt,
3987                                        ClassDef *inheritedFrom,bool invert,bool showAlways,
3988                                        QPtrDict<void> *visitedClasses)
3989 {
3990   int inhCount = 0;
3991   int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
3992   bool process = count>0;
3993   //printf("%s: countInheritedDecMembers: lt=%d process=%d count=%d invert=%d\n",
3994   //    name().data(),lt,process,count,invert);
3995   if ((process^invert) || showAlways)
3996   {
3997     if (m_impl->inherits)
3998     {
3999       BaseClassListIterator it(*m_impl->inherits);
4000       BaseClassDef *ibcd;
4001       for (it.toFirst();(ibcd=it.current());++it)
4002       {
4003         ClassDef *icd=ibcd->classDef;
4004         int lt1,lt2;
4005         if (icd->isLinkable())
4006         {
4007           convertProtectionLevel(lt,ibcd->prot,&lt1,&lt2);
4008           //printf("%s: convert %d->(%d,%d) prot=%d\n",
4009           //    icd->name().data(),lt,lt1,lt2,ibcd->prot);
4010           if (visitedClasses->find(icd)==0)
4011           {
4012             visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance
4013             if (lt1!=-1)
4014             {
4015               inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses);
4016             }
4017           }
4018         }
4019       }
4020     }
4021   }
4022   return inhCount;
4023 }
4024
4025 void ClassDef::getTitleForMemberListType(MemberListType type,
4026                QCString &title,QCString &subtitle)
4027 {
4028   SrcLangExt lang = getLanguage();
4029   QListIterator<LayoutDocEntry> eli(
4030       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
4031   LayoutDocEntry *lde;
4032   for (eli.toFirst();(lde=eli.current());++eli)
4033   {
4034     if (lde->kind()==LayoutDocEntry::MemberDecl)
4035     {
4036       LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
4037       if (lmd->type==type)
4038       {
4039         title = lmd->title(lang);
4040         subtitle = lmd->subtitle(lang);
4041         return;
4042       }
4043     }
4044   }
4045   title="";
4046   subtitle="";
4047 }
4048
4049 int ClassDef::countAdditionalInheritedMembers()
4050 {
4051   int totalCount=0;
4052   QListIterator<LayoutDocEntry> eli(
4053       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
4054   LayoutDocEntry *lde;
4055   for (eli.toFirst();(lde=eli.current());++eli)
4056   {
4057     if (lde->kind()==LayoutDocEntry::MemberDecl)
4058     {
4059       LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
4060       if (lmd->type!=MemberListType_friends) // friendship is not inherited
4061       {
4062         //MemberList *ml = getMemberList(lmd->type);
4063         //if (ml==0 || ml->numDecMembers()==0)
4064         //{
4065           QPtrDict<void> visited(17);
4066           totalCount+=countInheritedDecMembers(lmd->type,this,TRUE,FALSE,&visited);
4067         //}
4068       }
4069     }
4070   }
4071   //printf("countAdditonalInheritedMembers()=%d\n",totalCount);
4072   return totalCount;
4073 }
4074
4075 void ClassDef::writeAdditionalInheritedMembers(OutputList &ol)
4076 {
4077   //printf("**** writeAdditionalInheritedMembers()\n");
4078   QListIterator<LayoutDocEntry> eli(
4079       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
4080   LayoutDocEntry *lde;
4081   for (eli.toFirst();(lde=eli.current());++eli)
4082   {
4083     if (lde->kind()==LayoutDocEntry::MemberDecl)
4084     {
4085       LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
4086       if (lmd->type!=MemberListType_friends)
4087       {
4088         QPtrDict<void> visited(17);
4089         writeInheritedMemberDeclarations(ol,lmd->type,-1,lmd->title(getLanguage()),this,TRUE,FALSE,&visited);
4090       }
4091     }
4092   }
4093 }
4094
4095 int ClassDef::countMembersIncludingGrouped(MemberListType lt,
4096               ClassDef *inheritedFrom,bool additional)
4097 {
4098   int count=0;
4099   MemberList *ml = getMemberList(lt);
4100   if (ml)
4101   {
4102     count=ml->countInheritableMembers(inheritedFrom);
4103   }
4104   //printf("%s:countMembersIncludingGrouped: count=%d\n",name().data(),count);
4105   if (m_impl->memberGroupSDict)
4106   {
4107     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
4108     MemberGroup *mg;
4109     for (;(mg=mgli.current());++mgli)
4110     {
4111       bool hasOwnSection = !mg->allMembersInSameSection() ||
4112                            !m_impl->subGrouping; // group is in its own section
4113       if ((additional && hasOwnSection) || (!additional && !hasOwnSection))
4114       {
4115         count+=mg->countGroupedInheritedMembers(lt);
4116       }
4117     }
4118   }
4119   //printf("%s:countMembersIncludingGrouped(lt=%d,%s)=%d\n",
4120   //    name().data(),lt,ml?ml->listTypeAsString(ml->listType()).data():"<none>",count);
4121   return count;
4122 }
4123
4124 void ClassDef::writeInheritedMemberDeclarations(OutputList &ol,
4125                MemberListType lt,int lt2,const QCString &title,
4126                ClassDef *inheritedFrom,bool invert,bool showAlways,
4127                QPtrDict<void> *visitedClasses)
4128 {
4129   ol.pushGeneratorState();
4130   ol.disableAllBut(OutputGenerator::Html);
4131   int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
4132   bool process = count>0;
4133   //printf("%s: writeInheritedMemberDec: lt=%d process=%d invert=%d always=%d\n",
4134   //    name().data(),lt,process,invert,showAlways);
4135   if ((process^invert) || showAlways)
4136   {
4137     if (m_impl->inherits)
4138     {
4139       BaseClassListIterator it(*m_impl->inherits);
4140       BaseClassDef *ibcd;
4141       for (it.toFirst();(ibcd=it.current());++it)
4142       {
4143         ClassDef *icd=ibcd->classDef;
4144         if (icd->isLinkable())
4145         {
4146           int lt1,lt3;
4147           convertProtectionLevel(lt,ibcd->prot,&lt1,&lt3);
4148           if (lt2==-1 && lt3!=-1)
4149           {
4150             lt2=lt3;
4151           }
4152           //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot);
4153           if (visitedClasses->find(icd)==0)
4154           {
4155             visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance
4156             if (lt1!=-1)
4157             {
4158               icd->writeMemberDeclarations(ol,(MemberListType)lt1,
4159                   title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses);
4160             }
4161           }
4162           else
4163           {
4164             //printf("%s: class already visited!\n",icd->name().data());
4165           }
4166         }
4167       }
4168     }
4169   }
4170   ol.popGeneratorState();
4171 }
4172
4173 void ClassDef::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title,
4174                const char *subTitle,bool showInline,ClassDef *inheritedFrom,int lt2,
4175                bool invert,bool showAlways,QPtrDict<void> *visitedClasses)
4176 {
4177   //printf("%s: ClassDef::writeMemberDeclarations lt=%d lt2=%d\n",name().data(),lt,lt2);
4178   MemberList * ml = getMemberList(lt);
4179   MemberList * ml2 = getMemberList((MemberListType)lt2);
4180   if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function
4181   {
4182     if (ml)
4183     {
4184       VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this,0,0);
4185     }
4186   }
4187   else
4188   {
4189     //printf("%s::writeMemberDeclarations(%s) ml=%p ml2=%p\n",name().data(),title.data(),ml,ml2);
4190     QCString tt = title, st = subTitle;
4191     if (ml)
4192     {
4193       //printf("  writeDeclaration type=%d count=%d\n",lt,ml->numDecMembers());
4194       ml->writeDeclarations(ol,this,0,0,0,tt,st,definitionType(),FALSE,showInline,inheritedFrom,lt);
4195       tt.resize(0);
4196       st.resize(0);
4197     }
4198     if (ml2)
4199     {
4200       //printf("  writeDeclaration type=%d count=%d\n",lt2,ml2->numDecMembers());
4201       ml2->writeDeclarations(ol,this,0,0,0,tt,st,definitionType(),FALSE,showInline,inheritedFrom,lt);
4202     }
4203     static bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB");
4204     if (!inlineInheritedMembers) // show inherited members as separate lists
4205     {
4206       QPtrDict<void> visited(17);
4207       writeInheritedMemberDeclarations(ol,lt,lt2,title,
4208           inheritedFrom ? inheritedFrom : this,
4209           invert,showAlways,
4210           visitedClasses==0 ? &visited: visitedClasses);
4211     }
4212   }
4213 }
4214
4215 void ClassDef::addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
4216                         ClassDef *inheritedFrom,const QCString &inheritId)
4217 {
4218   //printf("** %s::addGroupedInheritedMembers(%p) inheritId=%s\n",name().data(),m_impl->memberGroupSDict,inheritId.data());
4219   if (m_impl->memberGroupSDict)
4220   {
4221     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
4222     MemberGroup *mg;
4223     for (;(mg=mgli.current());++mgli)
4224     {
4225       if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
4226       {
4227         mg->addGroupedInheritedMembers(ol,this,lt,inheritedFrom,inheritId);
4228       }
4229     }
4230   }
4231 }
4232
4233 void ClassDef::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline)
4234 {
4235   //printf("%s: ClassDef::writeMemberDocumentation()\n",name().data());
4236   MemberList * ml = getMemberList(lt);
4237   if (ml) ml->writeDocumentation(ol,displayName(),this,title,FALSE,showInline);
4238 }
4239
4240 void ClassDef::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt)
4241 {
4242   //printf("%s: ClassDef::writeSimpleMemberDocumentation()\n",name().data());
4243   MemberList * ml = getMemberList(lt);
4244   if (ml) ml->writeSimpleDocumentation(ol,this);
4245 }
4246
4247 void ClassDef::writePlainMemberDeclaration(OutputList &ol,
4248          MemberListType lt,bool inGroup,
4249          ClassDef *inheritedFrom,const char *inheritId)
4250 {
4251   //printf("%s: ClassDef::writePlainMemberDeclaration()\n",name().data());
4252   MemberList * ml = getMemberList(lt);
4253   if (ml)
4254   {
4255     ml->setInGroup(inGroup);
4256     ml->writePlainDeclarations(ol,this,0,0,0,definitionType(),inheritedFrom,inheritId);
4257   }
4258 }
4259
4260 bool ClassDef::isLocal() const
4261 {
4262   return m_impl->isLocal;
4263 }
4264
4265 ClassSDict *ClassDef::getClassSDict()
4266 {
4267   return m_impl->innerClasses;
4268 }
4269
4270 ClassDef::CompoundType ClassDef::compoundType() const
4271 {
4272   return m_impl->compType;
4273 }
4274
4275 BaseClassList *ClassDef::baseClasses() const
4276 {
4277   return m_impl->inherits;
4278 }
4279
4280 BaseClassList *ClassDef::subClasses() const
4281 {
4282   return m_impl->inheritedBy;
4283 }
4284
4285 MemberNameInfoSDict *ClassDef::memberNameInfoSDict() const
4286 {
4287   return m_impl->allMemberNameInfoSDict;
4288 }
4289
4290 Protection ClassDef::protection() const
4291 {
4292   return m_impl->prot;
4293 }
4294
4295 ArgumentList *ClassDef::templateArguments() const
4296 {
4297   return m_impl->tempArgs;
4298 }
4299
4300 NamespaceDef *ClassDef::getNamespaceDef() const
4301 {
4302   return m_impl->nspace;
4303 }
4304
4305 FileDef *ClassDef::getFileDef() const
4306 {
4307   return m_impl->fileDef;
4308 }
4309
4310 QDict<ClassDef> *ClassDef::getTemplateInstances() const
4311 {
4312   return m_impl->templateInstances;
4313 }
4314
4315 ClassDef *ClassDef::templateMaster() const
4316 {
4317   return m_impl->templateMaster;
4318 }
4319
4320 bool ClassDef::isTemplate() const
4321 {
4322   return m_impl->tempArgs!=0;
4323 }
4324
4325 IncludeInfo *ClassDef::includeInfo() const
4326 {
4327   return m_impl->incInfo;
4328 }
4329
4330 UsesClassDict *ClassDef::usedImplementationClasses() const
4331 {
4332   return m_impl->usesImplClassDict;
4333 }
4334
4335 UsesClassDict *ClassDef::usedByImplementationClasses() const
4336 {
4337   return m_impl->usedByImplClassDict;
4338 }
4339
4340 UsesClassDict *ClassDef::usedInterfaceClasses() const
4341 {
4342   return m_impl->usesIntfClassDict;
4343 }
4344
4345 bool ClassDef::isTemplateArgument() const
4346 {
4347   return m_impl->isTemplArg;
4348 }
4349
4350 bool ClassDef::isAbstract() const
4351 {
4352   return m_impl->isAbstract || (m_impl->spec&Entry::Abstract);
4353 }
4354
4355 bool ClassDef::isFinal() const
4356 {
4357   return m_impl->spec&Entry::Final;
4358 }
4359
4360 bool ClassDef::isSealed() const
4361 {
4362   return m_impl->spec&Entry::Sealed;
4363 }
4364
4365 bool ClassDef::isPublished() const
4366 {
4367   return m_impl->spec&Entry::Published;
4368 }
4369
4370 bool ClassDef::isForwardDeclared() const
4371 {
4372   return m_impl->spec&Entry::ForwardDecl;
4373 }
4374
4375 bool ClassDef::isObjectiveC() const
4376 {
4377   return getLanguage()==SrcLangExt_ObjC;
4378 }
4379
4380 bool ClassDef::isCSharp() const
4381 {
4382   return getLanguage()==SrcLangExt_CSharp;
4383 }
4384
4385 ClassDef *ClassDef::categoryOf() const
4386 {
4387   return m_impl->categoryOf;
4388 }
4389
4390 const QList<MemberList> &ClassDef::getMemberLists() const
4391 {
4392   return m_impl->memberLists;
4393 }
4394
4395 MemberGroupSDict *ClassDef::getMemberGroupSDict() const
4396 {
4397   return m_impl->memberGroupSDict;
4398 }
4399
4400 void ClassDef::setNamespace(NamespaceDef *nd)
4401 {
4402   m_impl->nspace = nd;
4403 }
4404
4405 void ClassDef::setFileDef(FileDef *fd)
4406 {
4407   m_impl->fileDef=fd;
4408 }
4409
4410 void ClassDef::setSubGrouping(bool enabled)
4411 {
4412   m_impl->subGrouping = enabled;
4413 }
4414
4415 void ClassDef::setProtection(Protection p)
4416 {
4417   m_impl->prot=p;
4418 }
4419
4420 void ClassDef::setIsStatic(bool b)
4421 {
4422   m_impl->isStatic=b;
4423 }
4424
4425 void ClassDef::setCompoundType(CompoundType t)
4426 {
4427   m_impl->compType = t;
4428 }
4429
4430 void ClassDef::setTemplateMaster(ClassDef *tm)
4431 {
4432   m_impl->templateMaster=tm;
4433 }
4434
4435 void ClassDef::makeTemplateArgument(bool b)
4436 {
4437   m_impl->isTemplArg = b;
4438 }
4439
4440 void ClassDef::setCategoryOf(ClassDef *cd)
4441 {
4442   m_impl->categoryOf = cd;
4443 }
4444
4445 void ClassDef::setUsedOnly(bool b)
4446 {
4447   m_impl->usedOnly = b;
4448 }
4449
4450 bool ClassDef::isUsedOnly() const
4451 {
4452   return m_impl->usedOnly;
4453 }
4454
4455 bool ClassDef::isSimple() const
4456 {
4457   return m_impl->isSimple;
4458 }
4459
4460 MemberDef *ClassDef::isSmartPointer() const
4461 {
4462   return m_impl->arrowOperator;
4463 }
4464
4465 void ClassDef::reclassifyMember(MemberDef *md,MemberType t)
4466 {
4467   md->setMemberType(t);
4468   QListIterator<MemberList> mli(m_impl->memberLists);
4469   MemberList *ml;
4470   for (;(ml=mli.current());++mli)
4471   {
4472     ml->remove(md);
4473   }
4474   insertMember(md);
4475 }
4476
4477 QCString ClassDef::anchor() const
4478 {
4479   QCString anc;
4480   if (isEmbeddedInOuterScope() && !Doxygen::generatingXmlOutput)
4481   {
4482     if (m_impl->templateMaster)
4483     {
4484       // point to the template of which this class is an instance
4485       anc = m_impl->templateMaster->getOutputFileBase();
4486     }
4487     else if (isReference())
4488     {
4489       // point to the external location
4490       anc = m_impl->fileName;
4491     }
4492     else
4493     {
4494       // normal locally defined class
4495       anc = convertNameToFile(m_impl->fileName);
4496     }
4497   }
4498   return anc;
4499 }
4500
4501 bool ClassDef::isEmbeddedInOuterScope() const
4502 {
4503   static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES");
4504   static bool inlineSimpleClasses = Config_getBool("INLINE_SIMPLE_STRUCTS");
4505
4506   Definition *container = getOuterScope();
4507
4508   bool containerLinkable =
4509     container &&
4510        (
4511         (container==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) || // global class in documented file
4512         container->isLinkableInProject() // class in documented scope
4513        );
4514
4515   // inline because of INLINE_GROUPED_CLASSES=YES ?
4516   bool b1 = (inlineGroupedClasses && partOfGroups()!=0); // a grouped class
4517   // inline because of INLINE_SIMPLE_STRUCTS=YES ?
4518   bool b2 = (inlineSimpleClasses && m_impl->isSimple && // a simple class
4519              (containerLinkable || // in a documented container
4520               partOfGroups()!=0    // or part of a group
4521              )
4522            );
4523   //printf("%s::isEmbeddedInOuterScope(): inlineGroupedClasses=%d "
4524   //       "inlineSimpleClasses=%d partOfGroups()=%p m_impl->isSimple=%d "
4525   //       "getOuterScope()=%s b1=%d b2=%d\n",
4526   //    name().data(),inlineGroupedClasses,inlineSimpleClasses,
4527   //    partOfGroups().pointer(),m_impl->isSimple,getOuterScope()?getOuterScope()->name().data():"<none>",b1,b2);
4528   return b1 || b2;  // either reason will do
4529 }
4530
4531 const ClassList *ClassDef::taggedInnerClasses() const
4532 {
4533   return m_impl->taggedInnerClasses;
4534 }
4535
4536 void ClassDef::addTaggedInnerClass(ClassDef *cd)
4537 {
4538   if (m_impl->taggedInnerClasses==0)
4539   {
4540     m_impl->taggedInnerClasses = new ClassList;
4541   }
4542   m_impl->taggedInnerClasses->append(cd);
4543 }
4544
4545 ClassDef *ClassDef::tagLessReference() const
4546 {
4547   return m_impl->tagLessRef;
4548 }
4549
4550 void ClassDef::setTagLessReference(ClassDef *cd)
4551 {
4552   m_impl->tagLessRef = cd;
4553 }
4554
4555 void ClassDef::removeMemberFromLists(MemberDef *md)
4556 {
4557   QListIterator<MemberList> mli(m_impl->memberLists);
4558   MemberList *ml;
4559   for (;(ml=mli.current());++mli)
4560   {
4561     ml->remove(md);
4562   }
4563 }
4564
4565 bool ClassDef::isJavaEnum() const
4566 {
4567   return m_impl->isJavaEnum;
4568 }
4569
4570 bool ClassDef::isGeneric() const
4571 {
4572   return m_impl->isGeneric;
4573 }
4574
4575 void ClassDef::setClassSpecifier(uint64 spec)
4576 {
4577   m_impl->spec = spec;
4578 }
4579
4580 bool ClassDef::isExtension() const
4581 {
4582   QCString n = name();
4583   int si = n.find('(');
4584   int ei = n.find(')');
4585   bool b = ei>si && n.mid(si+1,ei-si-1).stripWhiteSpace().isEmpty();
4586   return b;
4587 }
4588
4589 const ClassSDict *ClassDef::innerClasses() const
4590 {
4591   return m_impl->innerClasses;
4592 }
4593
4594 const FileList &ClassDef::usedFiles() const
4595 {
4596   return m_impl->files;
4597 }
4598
4599 const ArgumentList *ClassDef::typeConstraints() const
4600 {
4601   return m_impl->typeConstraints;
4602 }
4603
4604 const ExampleSDict *ClassDef::exampleList() const
4605 {
4606   return m_impl->exampleSDict;
4607 }
4608
4609 bool ClassDef::subGrouping() const
4610 {
4611   return m_impl->subGrouping;
4612 }
4613
4614 void ClassDef::setName(const char *name)
4615 {
4616   m_impl->isAnonymous = QCString(name).find('@')!=-1;
4617   Definition::setName(name);
4618 }
4619
4620 bool ClassDef::isAnonymous() const
4621 {
4622   return m_impl->isAnonymous;
4623 }