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