Orb/Doxygen/src/classdef.cpp
changeset 0 42188c7ea2d9
child 1 82f11024044a
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  * Copyright (C) 1997-2008 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 
       
    42 //-----------------------------------------------------------------------------
       
    43 
       
    44 //static inline MemberList *createNewMemberList(MemberList::ListType lt)
       
    45 //{
       
    46 //  MemberList *result = new MemberList(lt);
       
    47 //  return result;
       
    48 //}
       
    49 
       
    50 class ClassDefImpl
       
    51 {
       
    52   public:
       
    53     ClassDefImpl();
       
    54    ~ClassDefImpl();
       
    55     void init(const char *defFileName, const char *name,
       
    56               const QCString &ctStr, const char *fName);
       
    57 
       
    58     /*! file name that forms the base for the output file containing the
       
    59      *  class documentation. For compatibility with Qt (e.g. links via tag 
       
    60      *  files) this name cannot be derived from the class name directly.
       
    61      */
       
    62     QCString fileName;                   
       
    63 
       
    64     /*! Include information about the header file should be included
       
    65      *  in the documentation. 0 by default, set by setIncludeFile().
       
    66      */
       
    67     IncludeInfo *incInfo;                
       
    68 
       
    69     /*! List of base class (or super-classes) from which this class derives
       
    70      *  directly. 
       
    71      */
       
    72     BaseClassList *inherits;
       
    73 
       
    74     /*! List of sub-classes that directly derive from this class 
       
    75      */
       
    76     BaseClassList *inheritedBy;
       
    77 
       
    78     /*! Namespace this class is part of 
       
    79      *  (this is the inner most namespace in case of nested namespaces)
       
    80      */
       
    81     NamespaceDef  *nspace;              
       
    82 
       
    83     /*! File this class is defined in */
       
    84     FileDef *fileDef;
       
    85 
       
    86     /*! List of all members (including inherited members) */
       
    87     MemberNameInfoSDict *allMemberNameInfoSDict;
       
    88 
       
    89     /*! Template arguments of this class */
       
    90     ArgumentList *tempArgs;
       
    91 
       
    92     /*! Type constraints for template parameters */
       
    93     ArgumentList *typeConstraints;
       
    94 
       
    95     /*! Files that were used for generating the class documentation. */
       
    96     QStrList files;
       
    97 
       
    98     /*! Examples that use this class */
       
    99     ExampleSDict *exampleSDict;
       
   100 
       
   101     /*! Holds the kind of "class" this is. */
       
   102     ClassDef::CompoundType compType;
       
   103 
       
   104     /*! The protection level in which this class was found. 
       
   105      *  Typically Public, but for nested classes this can also be Protected
       
   106      *  or Private.
       
   107      */ 
       
   108     Protection prot;
       
   109 
       
   110     /*! The inner classes contained in this class. Will be 0 if there are
       
   111      *  no inner classes.
       
   112      */
       
   113     ClassSDict *innerClasses;
       
   114 
       
   115     /* classes for the collaboration diagram */
       
   116     UsesClassDict *usesImplClassDict;
       
   117     UsesClassDict *usedByImplClassDict;
       
   118     UsesClassDict *usesIntfClassDict;
       
   119 
       
   120     /*! Template instances that exists of this class, the key in the
       
   121      *  dictionary is the template argument list.
       
   122      */ 
       
   123     QDict<ClassDef> *templateInstances;
       
   124 
       
   125     /*! Template instances that exists of this class, as defined by variables.
       
   126      *  We do NOT want to document these individually. The key in the
       
   127      *  dictionary is the template argument list.
       
   128      */ 
       
   129     QDict<ClassDef> *variableInstances;
       
   130 
       
   131     QDict<int> *templBaseClassNames;
       
   132 
       
   133     /*! The class this class is an instance of. */
       
   134     ClassDef *templateMaster;
       
   135 
       
   136     /*! local class name which could be a typedef'ed alias name. */
       
   137     QCString className;
       
   138 
       
   139     /*! If this class is a Objective-C category, then this points to the
       
   140      *  class which is extended.
       
   141      */
       
   142     ClassDef *categoryOf;
       
   143 
       
   144     QList<MemberList> memberLists;
       
   145 
       
   146     /* user defined member groups */
       
   147     MemberGroupSDict *memberGroupSDict;
       
   148 
       
   149     /*! Is this an abstact class? */
       
   150     bool isAbstract;
       
   151 
       
   152     /*! Is the class part of an unnamed namespace? */
       
   153     bool isStatic;
       
   154 
       
   155     /*! Is the class part implemented in Objective C? */
       
   156     bool isObjC;
       
   157 
       
   158     /*! TRUE if classes members are merged with those of the base classes. */
       
   159     bool membersMerged;
       
   160 
       
   161     /*! TRUE if the class is defined in a source file rather than a header file. */
       
   162     bool isLocal;
       
   163 
       
   164     bool isTemplArg;
       
   165 
       
   166     /*! Does this class group its user-grouped members
       
   167      *  as a sub-section of the normal (public/protected/..) 
       
   168      *  groups?
       
   169      */
       
   170     bool subGrouping; 
       
   171 
       
   172     bool usedOnly;
       
   173 };
       
   174 
       
   175 void ClassDefImpl::init(const char *defFileName, const char *name,
       
   176                         const QCString &ctStr, const char *fName)
       
   177 {
       
   178   if (fName)
       
   179   {
       
   180     fileName=stripExtension(fName);
       
   181   }
       
   182   else
       
   183   {
       
   184     fileName=ctStr+name;
       
   185   }
       
   186   exampleSDict = 0;
       
   187   inherits    = 0;
       
   188   inheritedBy = 0;
       
   189   allMemberNameInfoSDict = 0;
       
   190   incInfo=0;
       
   191   tempArgs=0;
       
   192   typeConstraints=0;
       
   193   prot=Public;
       
   194   nspace=0;
       
   195   fileDef=0;
       
   196   usesImplClassDict=0;
       
   197   usedByImplClassDict=0;
       
   198   usesIntfClassDict=0;
       
   199   memberGroupSDict = 0;
       
   200   innerClasses = 0;
       
   201   subGrouping=Config_getBool("SUBGROUPING");
       
   202   templateInstances = 0;
       
   203   variableInstances = 0;
       
   204   templateMaster =0;
       
   205   templBaseClassNames = 0;
       
   206   isAbstract = FALSE;
       
   207   isStatic = FALSE;
       
   208   isTemplArg = FALSE;
       
   209   membersMerged = FALSE;
       
   210   categoryOf = 0;
       
   211   usedOnly = FALSE;
       
   212   //QCString ns;
       
   213   //extractNamespaceName(name,className,ns);
       
   214   //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data());
       
   215 
       
   216   if (((QCString)defFileName).right(5)!=".java" && 
       
   217       guessSection(defFileName)==Entry::SOURCE_SEC)
       
   218   {
       
   219     isLocal=TRUE;
       
   220   }
       
   221   else
       
   222   {
       
   223     isLocal=FALSE;
       
   224   }
       
   225 }
       
   226 
       
   227 ClassDefImpl::ClassDefImpl()
       
   228 {
       
   229 }
       
   230 
       
   231 ClassDefImpl::~ClassDefImpl()
       
   232 {
       
   233   delete inherits;
       
   234   delete inheritedBy;
       
   235   delete allMemberNameInfoSDict;
       
   236   delete exampleSDict;
       
   237   delete usesImplClassDict;
       
   238   delete usedByImplClassDict;
       
   239   delete usesIntfClassDict;
       
   240   delete incInfo;
       
   241   delete memberGroupSDict;
       
   242   delete innerClasses;
       
   243   delete templateInstances;
       
   244   delete variableInstances;
       
   245   delete templBaseClassNames;
       
   246   delete tempArgs;
       
   247   delete typeConstraints;
       
   248 }
       
   249 
       
   250 // constructs a new class definition
       
   251 ClassDef::ClassDef(
       
   252     const char *defFileName,int defLine,
       
   253     const char *nm,CompoundType ct,
       
   254     const char *lref,const char *fName,
       
   255     bool isSymbol) 
       
   256  : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm),0,0,isSymbol) 
       
   257 {
       
   258   visited=FALSE;
       
   259   setReference(lref);
       
   260   m_impl = new ClassDefImpl;
       
   261   m_impl->compType = ct;
       
   262   m_impl->isObjC   = FALSE;
       
   263   m_impl->init(defFileName,name(),compoundTypeString(),fName);
       
   264 
       
   265 }
       
   266 
       
   267 // destroy the class definition
       
   268 ClassDef::~ClassDef()
       
   269 {
       
   270   delete m_impl;
       
   271 }
       
   272 
       
   273 QCString ClassDef::getMemberListFileName() const
       
   274 {
       
   275   return convertNameToFile(compoundTypeString()+name()+"-members");
       
   276 }
       
   277 
       
   278 QCString ClassDef::displayName() const
       
   279 {
       
   280   static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
       
   281   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
   282   QCString n;
       
   283   if (vhdlOpt)
       
   284   {
       
   285     n = VhdlDocGen::getClassName(this);
       
   286   }
       
   287   else 
       
   288   {
       
   289     n=qualifiedNameWithTemplateParameters();
       
   290   }
       
   291   if (optimizeOutputForJava)
       
   292   {
       
   293     n=substitute(n,"::",".");
       
   294   }
       
   295   if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p")
       
   296   {
       
   297     n="<"+n.left(n.length()-2)+">";
       
   298   }
       
   299   return n;
       
   300 }
       
   301 
       
   302 // inserts a base class in the inheritance list
       
   303 void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p,
       
   304                                Specifier s,const char *t)
       
   305 {
       
   306   //printf("*** insert base class %s into %s\n",cd->name().data(),name().data());
       
   307   //inherits->inSort(new BaseClassDef(cd,p,s,t));
       
   308   if (m_impl->inherits==0)
       
   309   {
       
   310     m_impl->inherits = new BaseClassList;
       
   311     m_impl->inherits->setAutoDelete(TRUE);
       
   312   }
       
   313   m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t));
       
   314 }
       
   315 
       
   316 // inserts a sub class in the inherited list
       
   317 void ClassDef::insertSubClass(ClassDef *cd,Protection p,
       
   318                                 Specifier s,const char *t)
       
   319 {
       
   320   //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data());
       
   321   if (m_impl->inheritedBy==0)
       
   322   {
       
   323     m_impl->inheritedBy   = new BaseClassList;
       
   324     m_impl->inheritedBy->setAutoDelete(TRUE);
       
   325   }
       
   326   m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t));
       
   327 }
       
   328 
       
   329 void ClassDef::addMembersToMemberGroup()
       
   330 {
       
   331   QListIterator<MemberList> mli(m_impl->memberLists);
       
   332   MemberList *ml;
       
   333   for (mli.toFirst();(ml=mli.current());++mli)
       
   334   {
       
   335     if ((ml->listType()&MemberList::detailedLists)==0)
       
   336     {
       
   337       ::addMembersToMemberGroup(ml,&m_impl->memberGroupSDict,this);
       
   338     }
       
   339   }
       
   340 
       
   341   // add members inside sections to their groups
       
   342   if (m_impl->memberGroupSDict)
       
   343   {
       
   344     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
   345     MemberGroup *mg;
       
   346     for (;(mg=mgli.current());++mgli)
       
   347     {
       
   348       if (mg->allMembersInSameSection() && m_impl->subGrouping) 
       
   349       {
       
   350         //printf("addToDeclarationSection(%s)\n",mg->header().data());
       
   351         mg->addToDeclarationSection();
       
   352       }
       
   353     }
       
   354   }
       
   355 }
       
   356 
       
   357 // adds new member definition to the class
       
   358 void ClassDef::internalInsertMember(MemberDef *md,
       
   359                                     Protection prot,
       
   360                                     bool addToAllList
       
   361                                    )
       
   362 {
       
   363   //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden());
       
   364   if (md->isHidden()) return;
       
   365 
       
   366   if (!isReference())
       
   367   {
       
   368     static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
       
   369 
       
   370     /********************************************/
       
   371     /* insert member in the declaration section */
       
   372     /********************************************/
       
   373     if (md->isRelated() && (extractPrivate || prot!=Private))
       
   374     {
       
   375       addMemberToList(MemberList::related,md,true);
       
   376     }
       
   377     else if (md->isFriend())
       
   378     {
       
   379       addMemberToList(MemberList::friends,md,true);
       
   380     }
       
   381     else
       
   382     {
       
   383       switch (md->memberType())
       
   384       {
       
   385         case MemberDef::Signal: // Qt specific
       
   386           addMemberToList(MemberList::signals,md,true);
       
   387           break;
       
   388         case MemberDef::DCOP:   // KDE2 specific
       
   389           addMemberToList(MemberList::dcopMethods,md,true);
       
   390           break;
       
   391         case MemberDef::Property:
       
   392           addMemberToList(MemberList::properties,md,true);
       
   393           break;
       
   394         case MemberDef::Event:
       
   395           addMemberToList(MemberList::events,md,true);
       
   396           break;
       
   397         case MemberDef::Slot:   // Qt specific
       
   398           switch (prot)
       
   399           {
       
   400             case Protected: 
       
   401             case Package: // slots in packages are not possible!
       
   402               addMemberToList(MemberList::proSlots,md,true);
       
   403               break;
       
   404             case Public:    
       
   405               addMemberToList(MemberList::pubSlots,md,true);
       
   406               break;
       
   407             case Private:   
       
   408               addMemberToList(MemberList::priSlots,md,true);
       
   409               break;
       
   410           }
       
   411           break;
       
   412         default: // any of the other members
       
   413           if (md->isStatic())
       
   414           {
       
   415             if (md->isVariable())
       
   416             {
       
   417               switch (prot)
       
   418               {
       
   419                 case Protected: 
       
   420                   addMemberToList(MemberList::proStaticAttribs,md,true);
       
   421                   break;
       
   422                 case Package: 
       
   423                   addMemberToList(MemberList::pacStaticAttribs,md,true);
       
   424                   break;
       
   425                 case Public:    
       
   426                   addMemberToList(MemberList::pubStaticAttribs,md,true);
       
   427                   break;
       
   428                 case Private:   
       
   429                   addMemberToList(MemberList::priStaticAttribs,md,true);
       
   430                   break;
       
   431               }
       
   432             }
       
   433             else // function
       
   434             {
       
   435               switch (prot)
       
   436               {
       
   437                 case Protected: 
       
   438                   addMemberToList(MemberList::proStaticMethods,md,true);
       
   439                   break;
       
   440                 case Package: 
       
   441                   addMemberToList(MemberList::pacStaticMethods,md,true);
       
   442                   break;
       
   443                 case Public:    
       
   444                   addMemberToList(MemberList::pubStaticMethods,md,true);
       
   445                   break;
       
   446                 case Private:   
       
   447                   addMemberToList(MemberList::priStaticMethods,md,true);
       
   448                   break;
       
   449               }
       
   450             }
       
   451           }
       
   452           else // not static
       
   453           {
       
   454             if (md->isVariable())
       
   455             {
       
   456               switch (prot)
       
   457               {
       
   458                 case Protected: 
       
   459                   addMemberToList(MemberList::proAttribs,md,true);
       
   460                   break;
       
   461                 case Package:
       
   462                   addMemberToList(MemberList::pacAttribs,md,true);
       
   463                   break;
       
   464                 case Public:    
       
   465                   addMemberToList(MemberList::pubAttribs,md,true);
       
   466                   break;
       
   467                 case Private:   
       
   468                   addMemberToList(MemberList::priAttribs,md,true);
       
   469                   break;
       
   470               }
       
   471             }
       
   472             else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue())
       
   473             {
       
   474               switch (prot)
       
   475               {
       
   476                 case Protected: 
       
   477                   addMemberToList(MemberList::proTypes,md,true);
       
   478                   break;
       
   479                 case Package: 
       
   480                   addMemberToList(MemberList::pacTypes,md,true);
       
   481                   break;
       
   482                 case Public:    
       
   483                   addMemberToList(MemberList::pubTypes,md,true);
       
   484                   break;
       
   485                 case Private:   
       
   486                   addMemberToList(MemberList::priTypes,md,true);
       
   487                   break;
       
   488               }
       
   489             }
       
   490             else // member function
       
   491             {
       
   492               switch (prot)
       
   493               {
       
   494                 case Protected: 
       
   495                   addMemberToList(MemberList::proMethods,md,true);
       
   496                   break;
       
   497                 case Package: 
       
   498                   addMemberToList(MemberList::pacMethods,md,true);
       
   499                   break;
       
   500                 case Public:    
       
   501                   addMemberToList(MemberList::pubMethods,md,true);
       
   502                   break;
       
   503                 case Private:   
       
   504                   addMemberToList(MemberList::priMethods,md,true);
       
   505                   break;
       
   506               }
       
   507             }
       
   508           }
       
   509           break; 
       
   510       }
       
   511     }
       
   512 
       
   513     /*******************************************************/
       
   514     /* insert member in the detailed documentation section */
       
   515     /*******************************************************/
       
   516     if ((md->isRelated() && (extractPrivate || prot!=Private)) || md->isFriend())
       
   517     {
       
   518       addMemberToList(MemberList::relatedMembers,md,false);
       
   519     }
       
   520     else
       
   521     {
       
   522       switch (md->memberType())
       
   523       {
       
   524         case MemberDef::Property:
       
   525           addMemberToList(MemberList::propertyMembers,md,false);
       
   526           break;
       
   527         case MemberDef::Event:
       
   528           addMemberToList(MemberList::eventMembers,md,false);
       
   529           break;
       
   530         case MemberDef::Signal: // fall through
       
   531         case MemberDef::DCOP:
       
   532           addMemberToList(MemberList::functionMembers,md,false);
       
   533           break;
       
   534         case MemberDef::Slot:
       
   535           switch (prot)
       
   536           {
       
   537             case Protected: 
       
   538             case Package: 
       
   539             case Public:    
       
   540               addMemberToList(MemberList::functionMembers,md,false);
       
   541               break;
       
   542             case Private:   
       
   543               if (extractPrivate)
       
   544               {
       
   545                 addMemberToList(MemberList::functionMembers,md,false);
       
   546               }
       
   547               break;
       
   548           }
       
   549           break;
       
   550         default: // any of the other members
       
   551           if (prot!=Private || extractPrivate)
       
   552           {
       
   553             switch (md->memberType())
       
   554             {
       
   555               case MemberDef::Typedef:
       
   556                 addMemberToList(MemberList::typedefMembers,md,false);
       
   557                 break;
       
   558               case MemberDef::Enumeration:
       
   559                 addMemberToList(MemberList::enumMembers,md,false);
       
   560                 break;
       
   561               case MemberDef::EnumValue:
       
   562                 addMemberToList(MemberList::enumValMembers,md,false);
       
   563                 break;
       
   564               case MemberDef::Function:
       
   565                 if (md->isConstructor() || md->isDestructor())
       
   566                 {
       
   567                   MemberList *ml = createMemberList(MemberList::constructors);
       
   568                   ml->append(md);
       
   569                 }
       
   570                 else
       
   571                 {
       
   572                   addMemberToList(MemberList::functionMembers,md,false);
       
   573                 }
       
   574                 break;
       
   575               case MemberDef::Variable:
       
   576                 addMemberToList(MemberList::variableMembers,md,false);
       
   577                 break;
       
   578               default:
       
   579                 err("Unexpected member type %d found!\n",md->memberType());
       
   580             }
       
   581           }
       
   582           break; 
       
   583       }
       
   584     }
       
   585 
       
   586     /*************************************************/
       
   587     /* insert member in the appropriate member group */
       
   588     /*************************************************/
       
   589     // Note: this must be done AFTER inserting the member in the 
       
   590     // regular groups
       
   591     //addMemberToGroup(md,groupId);
       
   592     
       
   593   }
       
   594 
       
   595   if (md->virtualness()==Pure)
       
   596   {
       
   597     m_impl->isAbstract=TRUE;
       
   598   }
       
   599 
       
   600   //::addClassMemberNameToIndex(md);
       
   601   if (addToAllList && 
       
   602       !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
       
   603         md->isFriend() &&
       
   604         (QCString(md->typeString())=="friend class" || 
       
   605          QCString(md->typeString())=="friend struct" ||
       
   606          QCString(md->typeString())=="friend union")))
       
   607   {
       
   608     //printf("=======> adding member %s to class %s\n",md->name().data(),name().data());
       
   609     MemberInfo *mi = new MemberInfo((MemberDef *)md,
       
   610                                      prot,md->virtualness(),FALSE);
       
   611     MemberNameInfo *mni=0;
       
   612     if (m_impl->allMemberNameInfoSDict==0)
       
   613     {
       
   614       m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
       
   615       m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
       
   616     }
       
   617     if ((mni=m_impl->allMemberNameInfoSDict->find(md->name())))
       
   618     {
       
   619       mni->append(mi);
       
   620     }
       
   621     else
       
   622     {
       
   623       mni = new MemberNameInfo(md->name());
       
   624       mni->append(mi);
       
   625       m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni);
       
   626     }
       
   627   }
       
   628 }
       
   629 
       
   630 void ClassDef::insertMember(MemberDef *md)
       
   631 {
       
   632   internalInsertMember(md,md->protection(),TRUE);
       
   633 }
       
   634 
       
   635 // compute the anchors for all members
       
   636 void ClassDef::computeAnchors()
       
   637 {
       
   638   ClassDef *context = Config_getBool("INLINE_INHERITED_MEMB") ? this : 0;
       
   639   const char *letters = "abcdefghijklmnopqrstuvwxyz0123456789";
       
   640   QListIterator<MemberList> mli(m_impl->memberLists);
       
   641   MemberList *ml;
       
   642   int index = 0;
       
   643   for (mli.toFirst();(ml=mli.current());++mli)
       
   644   {
       
   645     if ((ml->listType()&MemberList::detailedLists)==0)
       
   646     {
       
   647       setAnchors(context,letters[index++],ml);
       
   648     }
       
   649   }
       
   650 
       
   651   if (m_impl->memberGroupSDict)
       
   652   {
       
   653     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
   654     MemberGroup *mg;
       
   655     for (;(mg=mgli.current());++mgli)
       
   656     {
       
   657       mg->setAnchors(context);
       
   658     }
       
   659   }
       
   660 }
       
   661 
       
   662 void ClassDef::distributeMemberGroupDocumentation()
       
   663 {
       
   664   if (m_impl->memberGroupSDict)
       
   665   {
       
   666     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
   667     MemberGroup *mg;
       
   668     for (;(mg=mgli.current());++mgli)
       
   669     {
       
   670       mg->distributeMemberGroupDocumentation();
       
   671     }
       
   672   }
       
   673 }
       
   674 
       
   675 void ClassDef::findSectionsInDocumentation()
       
   676 {
       
   677   docFindSections(documentation(),this,0,docFile());
       
   678   if (m_impl->memberGroupSDict)
       
   679   {
       
   680     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
   681     MemberGroup *mg;
       
   682     for (;(mg=mgli.current());++mgli)
       
   683     {
       
   684       mg->findSectionsInDocumentation();
       
   685     }
       
   686   }
       
   687   QListIterator<MemberList> mli(m_impl->memberLists);
       
   688   MemberList *ml;
       
   689   for (mli.toFirst();(ml=mli.current());++mli)
       
   690   {
       
   691     if ((ml->listType()&MemberList::detailedLists)==0)
       
   692     {
       
   693       ml->findSectionsInDocumentation();
       
   694     }
       
   695   }
       
   696 }
       
   697 
       
   698 
       
   699 // add a file name to the used files set
       
   700 void ClassDef::insertUsedFile(const char *f)
       
   701 {
       
   702   if (m_impl->files.find(f)==-1) m_impl->files.append(f);
       
   703   if (m_impl->templateInstances)
       
   704   {
       
   705     QDictIterator<ClassDef> qdi(*m_impl->templateInstances);
       
   706     ClassDef *cd;
       
   707     for (qdi.toFirst();(cd=qdi.current());++qdi)
       
   708     {
       
   709       cd->insertUsedFile(f);
       
   710     }
       
   711   }
       
   712 }
       
   713 
       
   714 static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd)
       
   715 {
       
   716   if (bcd->prot!=Public || bcd->virt!=Normal)
       
   717   {
       
   718     ol.startTypewriter();
       
   719     ol.docify(" [");
       
   720     QStrList sl;
       
   721     if (bcd->prot==Protected)    sl.append("protected");
       
   722     else if (bcd->prot==Private) sl.append("private");
       
   723     if (bcd->virt==Virtual)      sl.append("virtual");
       
   724     const char *s=sl.first();
       
   725     while (s)
       
   726     {
       
   727       ol.docify(s);
       
   728       s=sl.next();
       
   729       if (s) ol.docify(", ");
       
   730     }
       
   731     ol.docify("]");
       
   732     ol.endTypewriter();
       
   733   }
       
   734 }
       
   735 
       
   736 void ClassDef::setIncludeFile(FileDef *fd,
       
   737              const char *includeName,bool local, bool force)
       
   738 {
       
   739   //printf("ClassDef::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force);
       
   740   if (!m_impl->incInfo) m_impl->incInfo=new IncludeInfo;
       
   741   if ((includeName && m_impl->incInfo->includeName.isEmpty()) ||
       
   742       (fd!=0 && m_impl->incInfo->fileDef==0)
       
   743      )
       
   744   {
       
   745     //printf("Setting file info\n");
       
   746     m_impl->incInfo->fileDef     = fd;
       
   747     m_impl->incInfo->includeName = includeName;
       
   748     m_impl->incInfo->local       = local;
       
   749   }
       
   750   if (force && includeName) m_impl->incInfo->includeName = includeName;
       
   751 }
       
   752 
       
   753 // TODO: fix this: a nested template class can have multiple outer templates
       
   754 //ArgumentList *ClassDef::outerTemplateArguments() const
       
   755 //{
       
   756 //  int ti;
       
   757 //  ClassDef *pcd=0;
       
   758 //  int pi=0;
       
   759 //  if (m_impl->tempArgs) return m_impl->tempArgs;
       
   760 //  // find the outer most class scope
       
   761 //  while ((ti=name().find("::",pi))!=-1 && 
       
   762 //      (pcd=getClass(name().left(ti)))==0
       
   763 //        ) pi=ti+2;
       
   764 //  if (pcd)
       
   765 //  {
       
   766 //    return pcd->templateArguments();
       
   767 //  }
       
   768 //  return 0;
       
   769 //}
       
   770 
       
   771 static void searchTemplateSpecs(/*in*/  Definition *d,
       
   772                                 /*out*/ QList<ArgumentList> &result,
       
   773                                 /*out*/ QCString &name)
       
   774 {
       
   775   if (d->definitionType()==Definition::TypeClass)
       
   776   {
       
   777     if (d->getOuterScope())
       
   778     {
       
   779       searchTemplateSpecs(d->getOuterScope(),result,name);
       
   780     }
       
   781     ClassDef *cd=(ClassDef *)d;
       
   782     if (!name.isEmpty()) name+="::";
       
   783     name+=d->localName();
       
   784     bool isSpecialization = d->localName().find('<')!=-1;
       
   785     if (cd->templateArguments()) 
       
   786     {
       
   787       result.append(cd->templateArguments());
       
   788       if (!isSpecialization)
       
   789       {
       
   790         name+=tempArgListToString(cd->templateArguments());
       
   791       }
       
   792     }
       
   793   }
       
   794   else
       
   795   {
       
   796     name+=d->qualifiedName();
       
   797   }
       
   798 }
       
   799 
       
   800 static void writeTemplateSpec(OutputList &ol,Definition *d,
       
   801             const QCString &type)
       
   802 {
       
   803   QList<ArgumentList> specs;
       
   804   QCString name;
       
   805   searchTemplateSpecs(d,specs,name);
       
   806   if (specs.count()>0) // class has template scope specifiers
       
   807   {
       
   808     ol.startSubsubsection(); 
       
   809     QListIterator<ArgumentList> spi(specs);
       
   810     ArgumentList *al;
       
   811     for (spi.toFirst();(al=spi.current());++spi)
       
   812     {
       
   813       ol.docify("template<");
       
   814       Argument *a=al->first();
       
   815       while (a)
       
   816       {
       
   817         ol.docify(a->type);
       
   818         if (!a->name.isEmpty())
       
   819         {
       
   820           ol.docify(" ");
       
   821           ol.docify(a->name);
       
   822         }
       
   823         if (a->defval.length()!=0)
       
   824         {
       
   825           ol.docify(" = ");
       
   826           ol.docify(a->defval);
       
   827         } 
       
   828         a=al->next();
       
   829         if (a) ol.docify(", ");
       
   830       }
       
   831       ol.docify(">");
       
   832       ol.pushGeneratorState();
       
   833       ol.disableAllBut(OutputGenerator::Html);
       
   834       ol.lineBreak();
       
   835       ol.popGeneratorState();
       
   836     }
       
   837     ol.docify(type.lower()+" "+name);
       
   838     ol.endSubsubsection();
       
   839     ol.writeString("\n");
       
   840   }
       
   841 }
       
   842 
       
   843 void ClassDef::writeBriefDescription(OutputList &ol,bool exampleFlag)
       
   844 {
       
   845   if (!briefDescription().isEmpty())
       
   846   {
       
   847     ol.startParagraph();
       
   848     ol.parseDoc(briefFile(),briefLine(),this,0,
       
   849                 briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
       
   850     ol.pushGeneratorState();
       
   851     ol.disable(OutputGenerator::RTF);
       
   852     ol.writeString(" \n");
       
   853     ol.enable(OutputGenerator::RTF);
       
   854 
       
   855     if (Config_getBool("REPEAT_BRIEF") || 
       
   856         !documentation().isEmpty() || 
       
   857         exampleFlag
       
   858        )
       
   859     {
       
   860       ol.disableAllBut(OutputGenerator::Html);
       
   861       ol.startTextLink(0,"_details");
       
   862       ol.parseText(theTranslator->trMore());
       
   863       ol.endTextLink();
       
   864     }
       
   865     ol.popGeneratorState();
       
   866 
       
   867     //ol.pushGeneratorState();
       
   868     //ol.disable(OutputGenerator::RTF);
       
   869     //ol.newParagraph(); // FIXME:PARA
       
   870     //ol.popGeneratorState();
       
   871     ol.endParagraph();
       
   872   }
       
   873   ol.writeSynopsis();
       
   874 }
       
   875 
       
   876 // write the detailed description for this class
       
   877 void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType, bool exampleFlag, 
       
   878                                         const QCString &title)
       
   879 {
       
   880   if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || 
       
   881       !documentation().isEmpty() || 
       
   882       (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) ||
       
   883       exampleFlag)
       
   884   {
       
   885     ol.writeRuler();
       
   886     ol.pushGeneratorState();
       
   887       ol.disableAllBut(OutputGenerator::Html);
       
   888       ol.writeAnchor(0,"_details");
       
   889     ol.popGeneratorState();
       
   890     ol.startGroupHeader();
       
   891     ol.parseText(title);
       
   892     ol.endGroupHeader();
       
   893 
       
   894     ol.startTextBlock();
       
   895     
       
   896     writeTemplateSpec(ol,this,pageType);
       
   897     
       
   898     // repeat brief description
       
   899     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
       
   900     {
       
   901       ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
       
   902     }
       
   903     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") &&
       
   904         !documentation().isEmpty())
       
   905     {
       
   906       ol.pushGeneratorState();
       
   907         ol.disable(OutputGenerator::Man);
       
   908         ol.disable(OutputGenerator::RTF);
       
   909         //ol.newParagraph(); // FIXME:PARA
       
   910         ol.enableAll();
       
   911         ol.disableAllBut(OutputGenerator::Man);
       
   912         ol.writeString("\n\n");
       
   913       ol.popGeneratorState();
       
   914     }
       
   915     // write documentation
       
   916     if (!documentation().isEmpty())
       
   917     {
       
   918       ol.parseDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE);
       
   919     }
       
   920     // write type constraints
       
   921     writeTypeConstraints(ol,this,m_impl->typeConstraints);
       
   922 
       
   923     // write examples
       
   924     if (exampleFlag && m_impl->exampleSDict)
       
   925     {
       
   926       ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
       
   927       ol.startDescForItem();
       
   928       ol.startParagraph();
       
   929       writeExample(ol,m_impl->exampleSDict);
       
   930       ol.endParagraph();
       
   931       ol.endDescForItem();
       
   932       ol.endSimpleSect();
       
   933     }
       
   934     //ol.newParagraph();
       
   935     writeSourceDef(ol,name());
       
   936     ol.endTextBlock();
       
   937   }
       
   938   else
       
   939   {
       
   940     writeTemplateSpec(ol,this,pageType);
       
   941   }
       
   942 }
       
   943     
       
   944 void ClassDef::showUsedFiles(OutputList &ol)
       
   945 {
       
   946   ol.pushGeneratorState();
       
   947   ol.disable(OutputGenerator::Man);
       
   948   bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
       
   949 
       
   950   ol.writeRuler();
       
   951   if (fortranOpt)
       
   952   {
       
   953     ol.parseText(theTranslator->trGeneratedFromFilesFortran(
       
   954           m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType,
       
   955           m_impl->files.count()==1));
       
   956   }
       
   957   else
       
   958   {
       
   959     ol.parseText(theTranslator->trGeneratedFromFiles(
       
   960           m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType,
       
   961           m_impl->files.count()==1));  
       
   962   }
       
   963 
       
   964 
       
   965   bool first=TRUE;
       
   966   const char *file = m_impl->files.first();
       
   967   while (file)
       
   968   {
       
   969     bool ambig;
       
   970     FileDef *fd=findFileDef(Doxygen::inputNameDict,file,ambig);
       
   971     if (fd)
       
   972     {
       
   973       if (first)
       
   974       {
       
   975         first=FALSE;   
       
   976         ol.startItemList();
       
   977       }
       
   978 
       
   979       ol.startItemListItem();
       
   980       QCString path=fd->getPath();
       
   981       if (Config_getBool("FULL_PATH_NAMES"))
       
   982       {
       
   983         ol.docify(stripFromPath(path));
       
   984       }
       
   985 
       
   986       QCString fname = fd->name();
       
   987       if (!fd->getVersion().isEmpty()) // append version if available
       
   988       {
       
   989         fname += " (" + fd->getVersion() + ")";
       
   990       }
       
   991 
       
   992       // for HTML 
       
   993       ol.pushGeneratorState();
       
   994       ol.disableAllBut(OutputGenerator::Html);
       
   995       if (fd->generateSourceFile())
       
   996       {
       
   997         ol.writeObjectLink(0,fd->getSourceFileBase(),0,fname);
       
   998       }
       
   999       else if (fd->isLinkable())
       
  1000       {
       
  1001         ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
       
  1002             fname);
       
  1003       }
       
  1004       else
       
  1005       {
       
  1006         ol.docify(fname);
       
  1007       }
       
  1008       ol.popGeneratorState();
       
  1009 
       
  1010       // for other output formats
       
  1011       ol.pushGeneratorState();
       
  1012       ol.disable(OutputGenerator::Html);
       
  1013       if (fd->isLinkable())
       
  1014       {
       
  1015         ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
       
  1016             fname);
       
  1017       }
       
  1018       else
       
  1019       {
       
  1020         ol.docify(fname);
       
  1021       }
       
  1022       ol.popGeneratorState();
       
  1023 
       
  1024       ol.endItemListItem();
       
  1025     }
       
  1026     file=m_impl->files.next();
       
  1027   }
       
  1028   if (!first) ol.endItemList();
       
  1029 
       
  1030   ol.popGeneratorState();
       
  1031 }
       
  1032 
       
  1033 
       
  1034 void ClassDef::writeInheritanceGraph(OutputList &ol)
       
  1035 {
       
  1036   // count direct inheritance relations
       
  1037   int count=0;
       
  1038   BaseClassDef *ibcd;
       
  1039   if (m_impl->inheritedBy)
       
  1040   {
       
  1041     ibcd=m_impl->inheritedBy->first();
       
  1042     while (ibcd)
       
  1043     {
       
  1044       ClassDef *icd=ibcd->classDef;
       
  1045       if ( icd->isVisibleInHierarchy()) count++;
       
  1046       ibcd=m_impl->inheritedBy->next();
       
  1047     }
       
  1048   }
       
  1049   if (m_impl->inherits)
       
  1050   {
       
  1051     ibcd=m_impl->inherits->first();
       
  1052     while (ibcd)
       
  1053     {
       
  1054       ClassDef *icd=ibcd->classDef;
       
  1055       if ( icd->isVisibleInHierarchy()) count++;
       
  1056       ibcd=m_impl->inherits->next();
       
  1057     }
       
  1058   }
       
  1059 
       
  1060   
       
  1061   bool renderDiagram = FALSE;
       
  1062   if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_DIAGRAMS"))
       
  1063     // write class diagram using dot
       
  1064   {
       
  1065     DotClassGraph inheritanceGraph(this,DotNode::Inheritance);
       
  1066     if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig())
       
  1067     {
       
  1068       ol.pushGeneratorState();
       
  1069       ol.disable(OutputGenerator::Man);
       
  1070       ol.startDotGraph();
       
  1071       ol.parseText(theTranslator->trClassDiagram(displayName()));
       
  1072       ol.endDotGraph(inheritanceGraph);
       
  1073       ol.popGeneratorState();
       
  1074       renderDiagram = TRUE;
       
  1075     }
       
  1076   }
       
  1077   else if (Config_getBool("CLASS_DIAGRAMS") && count>0) 
       
  1078     // write class diagram using build-in generator
       
  1079   {
       
  1080     ClassDiagram diagram(this); // create a diagram of this class.
       
  1081     ol.startClassDiagram();
       
  1082     ol.disable(OutputGenerator::Man);
       
  1083     ol.parseText(theTranslator->trClassDiagram(displayName()));
       
  1084     ol.enable(OutputGenerator::Man);
       
  1085     ol.endClassDiagram(diagram,getOutputFileBase(),displayName());
       
  1086     renderDiagram = TRUE;
       
  1087   } 
       
  1088 
       
  1089   if (renderDiagram) // if we already show the inheritance relations graphically,
       
  1090                      // then hide the text version
       
  1091   {
       
  1092     ol.disableAllBut(OutputGenerator::Man);
       
  1093   }
       
  1094 
       
  1095   if (m_impl->inherits && (count=m_impl->inherits->count())>0)
       
  1096   {
       
  1097     ol.startParagraph();
       
  1098     //parseText(ol,theTranslator->trInherits()+" ");
       
  1099 
       
  1100     QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count());
       
  1101     QRegExp marker("@[0-9]+");
       
  1102     int index=0,newIndex,matchLen;
       
  1103     // now replace all markers in inheritLine with links to the classes
       
  1104     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
       
  1105     {
       
  1106       ol.parseText(inheritLine.mid(index,newIndex-index));
       
  1107       bool ok;
       
  1108       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
       
  1109       BaseClassDef *bcd=m_impl->inherits->at(entryIndex);
       
  1110       if (ok && bcd)
       
  1111       {
       
  1112         ClassDef *cd=bcd->classDef;
       
  1113 
       
  1114         // use the class name but with the template arguments as given
       
  1115         // in the inheritance relation
       
  1116         QCString displayName = insertTemplateSpecifierInScope(
       
  1117             cd->name(),bcd->templSpecifiers);
       
  1118 
       
  1119         if (cd->isLinkable())
       
  1120         {
       
  1121           if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
       
  1122           {
       
  1123             Doxygen::tagFile << "    <base";
       
  1124             if (bcd->prot==Protected)
       
  1125             {
       
  1126               Doxygen::tagFile << " protection=\"protected\"";
       
  1127             }
       
  1128             else if (bcd->prot==Private)
       
  1129             {
       
  1130               Doxygen::tagFile << " protection=\"private\"";
       
  1131             }
       
  1132             if (bcd->virt==Virtual)
       
  1133             {
       
  1134               Doxygen::tagFile << " virtualness=\"virtual\"";
       
  1135             }
       
  1136             Doxygen::tagFile << ">" << convertToXML(cd->name()) 
       
  1137                              << "</base>" << endl;
       
  1138           }
       
  1139           ol.writeObjectLink(cd->getReference(),
       
  1140                              cd->getOutputFileBase(),
       
  1141                              0,
       
  1142                              displayName);
       
  1143         }
       
  1144         else
       
  1145         {
       
  1146           ol.docify(displayName);
       
  1147         }
       
  1148       }
       
  1149       else
       
  1150       {
       
  1151         err("Error: invalid marker %d in inherits list!\n",entryIndex);
       
  1152       }
       
  1153       index=newIndex+matchLen;
       
  1154     } 
       
  1155     ol.parseText(inheritLine.right(inheritLine.length()-index));
       
  1156     ol.endParagraph();
       
  1157   }
       
  1158 
       
  1159   // write subclasses
       
  1160   if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0)
       
  1161   {
       
  1162     ol.startParagraph();
       
  1163     QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count());
       
  1164     QRegExp marker("@[0-9]+");
       
  1165     int index=0,newIndex,matchLen;
       
  1166     // now replace all markers in inheritLine with links to the classes
       
  1167     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
       
  1168     {
       
  1169       ol.parseText(inheritLine.mid(index,newIndex-index));
       
  1170       bool ok;
       
  1171       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
       
  1172       BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex);
       
  1173       if (ok && bcd)
       
  1174       {
       
  1175         ClassDef *cd=bcd->classDef;
       
  1176         if (cd->isLinkable())
       
  1177         {
       
  1178           ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName());
       
  1179         }
       
  1180         else
       
  1181         {
       
  1182           ol.docify(cd->displayName());
       
  1183         }
       
  1184         writeInheritanceSpecifier(ol,bcd);
       
  1185       }
       
  1186       index=newIndex+matchLen;
       
  1187     } 
       
  1188     ol.parseText(inheritLine.right(inheritLine.length()-index));
       
  1189     ol.endParagraph();
       
  1190   }
       
  1191 
       
  1192   if (renderDiagram) 
       
  1193   {
       
  1194     ol.enableAll();
       
  1195   }
       
  1196 }
       
  1197 
       
  1198 void ClassDef::writeCollaborationGraph(OutputList &ol)
       
  1199 {
       
  1200   if (Config_getBool("HAVE_DOT") /*&& Config_getBool("COLLABORATION_GRAPH")*/)
       
  1201   {
       
  1202     DotClassGraph usageImplGraph(this,DotNode::Collaboration);
       
  1203     if (!usageImplGraph.isTrivial())
       
  1204     {
       
  1205       ol.pushGeneratorState();
       
  1206       ol.disable(OutputGenerator::Man);
       
  1207       ol.startDotGraph();
       
  1208       ol.parseText(theTranslator->trCollaborationDiagram(displayName()));
       
  1209       ol.endDotGraph(usageImplGraph);
       
  1210       ol.popGeneratorState();
       
  1211     }
       
  1212   }
       
  1213 }
       
  1214 
       
  1215 void ClassDef::writeIncludeFiles(OutputList &ol)
       
  1216 {
       
  1217   if (m_impl->incInfo /*&& Config_getBool("SHOW_INCLUDE_FILES")*/)
       
  1218   {
       
  1219     QCString nm=m_impl->incInfo->includeName.isEmpty() ? 
       
  1220       (m_impl->incInfo->fileDef ?
       
  1221        m_impl->incInfo->fileDef->docName().data() : "" 
       
  1222       ) :
       
  1223       m_impl->incInfo->includeName.data();
       
  1224     if (!nm.isEmpty())
       
  1225     {
       
  1226       ol.startParagraph();
       
  1227       ol.startTypewriter();
       
  1228       bool isIDLorJava = nm.right(4)==".idl" || 
       
  1229                          nm.right(5)==".pidl" || 
       
  1230                          nm.right(5)==".java";
       
  1231       if (isIDLorJava)
       
  1232       {
       
  1233         ol.docify("import ");
       
  1234       }
       
  1235       else if (isObjectiveC())
       
  1236       {
       
  1237         ol.docify("#import ");
       
  1238       }
       
  1239       else
       
  1240       {
       
  1241         ol.docify("#include ");
       
  1242       }
       
  1243       if (m_impl->incInfo->local || isIDLorJava)
       
  1244         ol.docify("\"");
       
  1245       else
       
  1246         ol.docify("<");
       
  1247       ol.pushGeneratorState();
       
  1248       ol.disable(OutputGenerator::Html);
       
  1249       ol.docify(nm);
       
  1250       ol.disableAllBut(OutputGenerator::Html);
       
  1251       ol.enable(OutputGenerator::Html);
       
  1252       if (m_impl->incInfo->fileDef)
       
  1253       {
       
  1254         ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm);
       
  1255       }
       
  1256       else
       
  1257       {
       
  1258         ol.docify(nm);
       
  1259       }
       
  1260       ol.popGeneratorState();
       
  1261       if (m_impl->incInfo->local || isIDLorJava)
       
  1262         ol.docify("\"");
       
  1263       else
       
  1264         ol.docify(">");
       
  1265       if (isIDLorJava) 
       
  1266         ol.docify(";");
       
  1267       ol.endTypewriter();
       
  1268       ol.endParagraph();
       
  1269     }
       
  1270   }
       
  1271 }
       
  1272 
       
  1273 void ClassDef::writeAllMembersLink(OutputList &ol)
       
  1274 {
       
  1275   // write link to list of all members (HTML only)
       
  1276   if (m_impl->allMemberNameInfoSDict &&
       
  1277       !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")
       
  1278      )
       
  1279   {
       
  1280     ol.pushGeneratorState();
       
  1281     ol.disableAllBut(OutputGenerator::Html);
       
  1282     ol.startParagraph();
       
  1283     ol.startTextLink(getMemberListFileName(),0);
       
  1284     ol.parseText(theTranslator->trListOfAllMembers());
       
  1285     ol.endTextLink();
       
  1286     ol.endParagraph();
       
  1287     ol.enableAll();
       
  1288     ol.popGeneratorState();
       
  1289   }
       
  1290 }
       
  1291 
       
  1292 void ClassDef::writeMemberGroups(OutputList &ol)
       
  1293 {
       
  1294   // write user defined member groups
       
  1295   if (m_impl->memberGroupSDict)
       
  1296   {
       
  1297     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
  1298     MemberGroup *mg;
       
  1299     for (;(mg=mgli.current());++mgli)
       
  1300     {
       
  1301       if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
       
  1302       {
       
  1303         mg->writeDeclarations(ol,this,0,0,0);
       
  1304       }
       
  1305       else // add this group to the corresponding member section
       
  1306       {
       
  1307         //printf("addToDeclarationSection(%s)\n",mg->header().data());
       
  1308         //mg->addToDeclarationSection();
       
  1309       }
       
  1310     }
       
  1311   }
       
  1312 }
       
  1313 
       
  1314 void ClassDef::writeNestedClasses(OutputList &ol,const QCString &title)
       
  1315 {
       
  1316   // nested classes
       
  1317   if (m_impl->innerClasses) 
       
  1318   {
       
  1319     m_impl->innerClasses->writeDeclaration(ol,0,title,TRUE);
       
  1320   }
       
  1321 }
       
  1322 
       
  1323 void ClassDef::startMemberDocumentation(OutputList &ol)
       
  1324 {
       
  1325   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
  1326   {
       
  1327     ol.disable(OutputGenerator::Html);
       
  1328     Doxygen::suppressDocWarnings = TRUE;
       
  1329   }
       
  1330 }
       
  1331 
       
  1332 void ClassDef::endMemberDocumentation(OutputList &ol)
       
  1333 {
       
  1334   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
  1335   {
       
  1336     ol.enable(OutputGenerator::Html);
       
  1337     Doxygen::suppressDocWarnings = FALSE;
       
  1338   }
       
  1339 }
       
  1340 
       
  1341 void ClassDef::startMemberDeclarations(OutputList &ol)
       
  1342 {
       
  1343   ol.startMemberSections();
       
  1344 }
       
  1345 
       
  1346 void ClassDef::endMemberDeclarations(OutputList &ol)
       
  1347 {
       
  1348   ol.endMemberSections();
       
  1349 }
       
  1350 
       
  1351 void ClassDef::writeAuthorSection(OutputList &ol)
       
  1352 {
       
  1353   ol.pushGeneratorState();
       
  1354   ol.disableAllBut(OutputGenerator::Man);
       
  1355   ol.writeString("\n");
       
  1356   ol.startGroupHeader();
       
  1357   ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
       
  1358   ol.endGroupHeader();
       
  1359   ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
       
  1360   ol.popGeneratorState();
       
  1361 }
       
  1362 
       
  1363 // write all documentation for this class
       
  1364 void ClassDef::writeDocumentation(OutputList &ol)
       
  1365 {
       
  1366   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
       
  1367   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
  1368   QCString pageType = " ";
       
  1369   QCString pageTitle = " ";
       
  1370     
       
  1371   pageType += compoundTypeString();
       
  1372   toupper(pageType.at(1));
       
  1373   if (fortranOpt)
       
  1374   {
       
  1375     pageTitle = theTranslator->trCompoundReferenceFortran(displayName(),
       
  1376               m_impl->compType,
       
  1377               m_impl->tempArgs != 0);  
       
  1378   }
       
  1379   else if (vhdlOpt)
       
  1380   {
       
  1381     // TODO: translate
       
  1382     pageTitle = VhdlDocGen::getClassTitle(this)+" Reference";
       
  1383   }
       
  1384   else
       
  1385   {
       
  1386     pageTitle = theTranslator->trCompoundReference(displayName(),
       
  1387               m_impl->compType == Interface && m_impl->isObjC ? Class : m_impl->compType,
       
  1388               m_impl->tempArgs != 0);
       
  1389   }
       
  1390   
       
  1391   startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,TRUE);  
       
  1392   if (getOuterScope()!=Doxygen::globalScope)
       
  1393   {
       
  1394     writeNavigationPath(ol);
       
  1395   }
       
  1396   ol.endQuickIndices();
       
  1397   ol.startContents();
       
  1398   startTitle(ol,getOutputFileBase());
       
  1399   ol.parseText(pageTitle);
       
  1400   addGroupListToTitle(ol,this);
       
  1401   endTitle(ol,getOutputFileBase(),name());
       
  1402 
       
  1403   {
       
  1404     ol.pushGeneratorState();
       
  1405     ol.disableAllBut(OutputGenerator::Html);
       
  1406     ol.writeString("<!-- doxytag: class=\"");
       
  1407     ol.docify(name());
       
  1408     ol.writeString("\" -->");
       
  1409     if (m_impl->inherits && m_impl->inherits->count()>0)
       
  1410     {
       
  1411       BaseClassListIterator bli(*m_impl->inherits);
       
  1412       ol.writeString("<!-- doxytag: inherits=\"");
       
  1413       BaseClassDef *bcd=0;
       
  1414       bool first=TRUE;
       
  1415       for (bli.toFirst();(bcd=bli.current());++bli)
       
  1416       {
       
  1417         if (!first) ol.writeString(",");
       
  1418         ol.docify(bcd->classDef->name());
       
  1419         first=FALSE;
       
  1420       }
       
  1421       ol.writeString("\" -->");
       
  1422     }
       
  1423     ol.popGeneratorState();
       
  1424   }
       
  1425 
       
  1426   Doxygen::indexList.addIndexItem(this,0);
       
  1427 
       
  1428   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
       
  1429   {
       
  1430     Doxygen::tagFile << "  <compound kind=\"" << compoundTypeString();
       
  1431     Doxygen::tagFile << "\"";
       
  1432     if (isObjectiveC()) { Doxygen::tagFile << " objc=\"yes\""; }
       
  1433     Doxygen::tagFile << ">" << endl;
       
  1434     Doxygen::tagFile << "    <name>" << convertToXML(name()) << "</name>" << endl;
       
  1435     Doxygen::tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
       
  1436     if (m_impl->tempArgs)
       
  1437     {
       
  1438       ArgumentListIterator ali(*m_impl->tempArgs);
       
  1439       Argument *a;
       
  1440       for (;(a=ali.current());++ali)
       
  1441       {
       
  1442         Doxygen::tagFile << "    <templarg>" << convertToXML(a->name) << "</templarg>" << endl;
       
  1443       }
       
  1444     }
       
  1445   }
       
  1446 
       
  1447   if (Doxygen::searchIndex)
       
  1448   {
       
  1449     Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase());
       
  1450     Doxygen::searchIndex->addWord(localName(),TRUE);
       
  1451   }
       
  1452   bool exampleFlag=hasExamples();
       
  1453 
       
  1454   //---------------------------------------- start flexible part -------------------------------
       
  1455 
       
  1456   QListIterator<LayoutDocEntry> eli(
       
  1457       LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
       
  1458   LayoutDocEntry *lde;
       
  1459   for (eli.toFirst();(lde=eli.current());++eli)
       
  1460   {
       
  1461     switch (lde->kind())
       
  1462     {
       
  1463       case LayoutDocEntry::BriefDesc: 
       
  1464         writeBriefDescription(ol,exampleFlag);
       
  1465         break; 
       
  1466       case LayoutDocEntry::ClassIncludes: 
       
  1467         writeIncludeFiles(ol);
       
  1468         break;
       
  1469       case LayoutDocEntry::ClassInheritanceGraph: 
       
  1470         writeInheritanceGraph(ol); 
       
  1471         break; 
       
  1472       case LayoutDocEntry::ClassCollaborationGraph: 
       
  1473         writeCollaborationGraph(ol); 
       
  1474         break; 
       
  1475       case LayoutDocEntry::ClassAllMembersLink: 
       
  1476         writeAllMembersLink(ol);
       
  1477         break;
       
  1478       case LayoutDocEntry::MemberDeclStart: 
       
  1479         startMemberDeclarations(ol);
       
  1480         break; 
       
  1481       case LayoutDocEntry::MemberGroups: 
       
  1482         writeMemberGroups(ol);
       
  1483         break;
       
  1484       case LayoutDocEntry::MemberDecl: 
       
  1485         {
       
  1486           LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
       
  1487           writeMemberDeclarations(ol,lmd->type,lmd->title,lmd->subscript);
       
  1488         }
       
  1489         break; 
       
  1490       case LayoutDocEntry::ClassNestedClasses: 
       
  1491         {
       
  1492           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
       
  1493           writeNestedClasses(ol,ls->title);
       
  1494         }
       
  1495         break;
       
  1496       case LayoutDocEntry::MemberDeclEnd: 
       
  1497         endMemberDeclarations(ol);
       
  1498         break;
       
  1499       case LayoutDocEntry::DetailedDesc: 
       
  1500         {
       
  1501           LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;
       
  1502           writeDetailedDescription(ol,pageType,exampleFlag,ls->title);
       
  1503         }
       
  1504         break; 
       
  1505       case LayoutDocEntry::MemberDefStart: 
       
  1506         startMemberDocumentation(ol);
       
  1507         break; 
       
  1508       case LayoutDocEntry::MemberDef: 
       
  1509         {
       
  1510           LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
       
  1511           writeMemberDocumentation(ol,lmd->type,lmd->title);
       
  1512         }
       
  1513         break; 
       
  1514       case LayoutDocEntry::MemberDefEnd: 
       
  1515         endMemberDocumentation(ol);
       
  1516         break;
       
  1517       case LayoutDocEntry::ClassUsedFiles: 
       
  1518         showUsedFiles(ol);
       
  1519         break;
       
  1520       case LayoutDocEntry::AuthorSection: 
       
  1521         writeAuthorSection(ol);
       
  1522         break;
       
  1523       case LayoutDocEntry::NamespaceNestedNamespaces:
       
  1524       case LayoutDocEntry::NamespaceClasses:
       
  1525       case LayoutDocEntry::FileClasses:
       
  1526       case LayoutDocEntry::FileNamespaces:
       
  1527       case LayoutDocEntry::FileIncludes:
       
  1528       case LayoutDocEntry::FileIncludeGraph:
       
  1529       case LayoutDocEntry::FileIncludedByGraph: 
       
  1530       case LayoutDocEntry::FileSourceLink:
       
  1531       case LayoutDocEntry::GroupClasses: 
       
  1532       case LayoutDocEntry::GroupNamespaces:
       
  1533       case LayoutDocEntry::GroupDirs: 
       
  1534       case LayoutDocEntry::GroupNestedGroups: 
       
  1535       case LayoutDocEntry::GroupFiles:
       
  1536       case LayoutDocEntry::GroupGraph: 
       
  1537       case LayoutDocEntry::GroupPageDocs:
       
  1538       case LayoutDocEntry::DirSubDirs:
       
  1539       case LayoutDocEntry::DirFiles:
       
  1540       case LayoutDocEntry::DirGraph:
       
  1541         err("Internal inconsistency: member %d should not be part of "
       
  1542             "LayoutDocManager::Class entry list\n",lde->kind());
       
  1543         break;
       
  1544     }
       
  1545   }
       
  1546 
       
  1547   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
       
  1548   {
       
  1549     writeDocAnchorsToTagFile();
       
  1550     Doxygen::tagFile << "  </compound>" << endl;
       
  1551   }
       
  1552  
       
  1553   endFile(ol);
       
  1554 
       
  1555   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
       
  1556   {
       
  1557     writeMemberPages(ol);
       
  1558   }
       
  1559 }
       
  1560 
       
  1561 void ClassDef::writeMemberPages(OutputList &ol)
       
  1562 {
       
  1563   ///////////////////////////////////////////////////////////////////////////
       
  1564   //// Member definitions on separate pages
       
  1565   ///////////////////////////////////////////////////////////////////////////
       
  1566 
       
  1567   ol.pushGeneratorState();
       
  1568   ol.disableAllBut(OutputGenerator::Html);
       
  1569   
       
  1570   QListIterator<MemberList> mli(m_impl->memberLists);
       
  1571   MemberList *ml;
       
  1572   for (mli.toFirst();(ml=mli.current());++mli)
       
  1573   {
       
  1574     if (ml->listType()&MemberList::detailedLists)
       
  1575     {
       
  1576       ml->writeDocumentationPage(ol,name(),this);
       
  1577     }
       
  1578   }
       
  1579 
       
  1580   ol.popGeneratorState();
       
  1581 }
       
  1582 
       
  1583 void ClassDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
       
  1584 {
       
  1585   static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
       
  1586 
       
  1587   ol.writeString("      <div class=\"navtab\">\n");
       
  1588   ol.writeString("        <table>\n");
       
  1589 
       
  1590   if (m_impl->allMemberNameInfoSDict)
       
  1591   {
       
  1592     MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
       
  1593     MemberNameInfo *mni;
       
  1594     for (;(mni=mnili.current());++mnili)
       
  1595     {
       
  1596       MemberNameInfoIterator mnii(*mni);
       
  1597       MemberInfo *mi;
       
  1598       for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  1599       {
       
  1600         MemberDef *md=mi->memberDef;
       
  1601         if (md->getClassDef()==this && md->isLinkable())
       
  1602         {
       
  1603           ol.writeString("          <tr><td class=\"navtab\">");
       
  1604           if (md->isLinkableInProject())
       
  1605           {
       
  1606             if (md==currentMd) // selected item => highlight
       
  1607             {
       
  1608               ol.writeString("<a class=\"qindexHL\" ");
       
  1609             }
       
  1610             else
       
  1611             {
       
  1612               ol.writeString("<a class=\"qindex\" ");
       
  1613             }
       
  1614             ol.writeString("href=\"");
       
  1615             if (createSubDirs) ol.writeString("../../");
       
  1616             ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
       
  1617             ol.writeString("\">");
       
  1618             ol.writeString(md->name());
       
  1619             ol.writeString("</a>");
       
  1620           }
       
  1621           ol.writeString("</td></tr>\n");
       
  1622         }
       
  1623       }
       
  1624     }
       
  1625   }
       
  1626 
       
  1627   ol.writeString("        </table>\n");
       
  1628   ol.writeString("      </div>\n");
       
  1629 }
       
  1630 
       
  1631 
       
  1632 
       
  1633 void ClassDef::writeDocumentationForInnerClasses(OutputList &ol)
       
  1634 {
       
  1635   // write inner classes after the parent, so the tag files contain
       
  1636   // the definition in proper order!
       
  1637   if (m_impl->innerClasses)
       
  1638   {
       
  1639     ClassSDict::Iterator cli(*m_impl->innerClasses);
       
  1640     ClassDef *innerCd;
       
  1641     for (cli.toFirst();(innerCd=cli.current());++cli)
       
  1642     {
       
  1643       if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 &&
       
  1644           (innerCd->protection()!=Private || Config_getBool("EXTRACT_PRIVATE"))
       
  1645          )
       
  1646       {
       
  1647         msg("Generating docs for nested compound %s...\n",innerCd->name().data());
       
  1648         innerCd->writeDocumentation(ol);
       
  1649         innerCd->writeMemberList(ol);
       
  1650       }
       
  1651       innerCd->writeDocumentationForInnerClasses(ol);
       
  1652     }
       
  1653   }
       
  1654 }
       
  1655 
       
  1656 // write the list of all (inherited) members for this class
       
  1657 void ClassDef::writeMemberList(OutputList &ol)
       
  1658 {
       
  1659   static bool cOpt    = Config_getBool("OPTIMIZE_OUTPUT_FOR_C");
       
  1660   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
  1661   if (m_impl->allMemberNameInfoSDict==0 || cOpt) return;
       
  1662   // only for HTML
       
  1663   ol.pushGeneratorState();
       
  1664   ol.disableAllBut(OutputGenerator::Html);
       
  1665 
       
  1666   QCString memListFile = getMemberListFileName();
       
  1667   startFile(ol,memListFile,memListFile,
       
  1668             theTranslator->trMemberList(),HLI_ClassVisible);
       
  1669   startTitle(ol,0);
       
  1670   ol.parseText(displayName()+" "+theTranslator->trMemberList());
       
  1671   endTitle(ol,0,0);
       
  1672   ol.parseText(theTranslator->trThisIsTheListOfAllMembers());
       
  1673   ol.writeObjectLink(getReference(),getOutputFileBase(),0,displayName());
       
  1674   ol.parseText(theTranslator->trIncludingInheritedMembers());
       
  1675   
       
  1676   //ol.startItemList();
       
  1677   ol.writeString("<table>\n");
       
  1678   
       
  1679   //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first();
       
  1680   MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict); 
       
  1681   MemberNameInfo *mni;
       
  1682   for (mnii.toFirst();(mni=mnii.current());++mnii)
       
  1683   {
       
  1684     MemberInfo *mi=mni->first();
       
  1685     while (mi)
       
  1686     {
       
  1687       MemberDef *md=mi->memberDef;
       
  1688       ClassDef  *cd=md->getClassDef();
       
  1689       Protection prot = mi->prot;
       
  1690       Specifier virt=md->virtualness();
       
  1691       
       
  1692       //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n",
       
  1693       //    name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited);
       
  1694 
       
  1695 
       
  1696       if (cd && !md->name().isEmpty() && md->name()[0]!='@')
       
  1697       {
       
  1698         bool memberWritten=FALSE;
       
  1699         if (cd->isLinkable() && md->isLinkable()) 
       
  1700           // create a link to the documentation
       
  1701         {
       
  1702           QCString name=mi->ambiguityResolutionScope+md->name();
       
  1703           //ol.writeListItem();
       
  1704           ol.writeString("  <tr class=\"memlist\"><td>");
       
  1705           if (cd->isObjectiveC())
       
  1706           {
       
  1707             if (md->isObjCMethod())
       
  1708             {
       
  1709               if (md->isStatic())
       
  1710                 ol.writeString("+&nbsp;</td><td>");
       
  1711               else
       
  1712                 ol.writeString("-&nbsp;</td><td>");
       
  1713             }
       
  1714             else
       
  1715               ol.writeString("</td><td>");
       
  1716           }
       
  1717           if (md->isObjCMethod())
       
  1718           {
       
  1719             ol.writeObjectLink(md->getReference(),
       
  1720                 md->getOutputFileBase(),
       
  1721                 md->anchor(),md->name());
       
  1722           }
       
  1723           else
       
  1724           {
       
  1725             //Definition *bd = md->getGroupDef();
       
  1726             //if (bd==0) bd=cd;
       
  1727             ol.writeObjectLink(md->getReference(),
       
  1728                 md->getOutputFileBase(),
       
  1729                 md->anchor(),name);
       
  1730 
       
  1731             if ( md->isFunction() || md->isSignal() || md->isSlot() ||
       
  1732                 (md->isFriend() && md->argsString())) 
       
  1733               ol.docify(md->argsString());
       
  1734             else if (md->isEnumerate())
       
  1735               ol.parseText(" "+theTranslator->trEnumName());
       
  1736             else if (md->isEnumValue())
       
  1737               ol.parseText(" "+theTranslator->trEnumValue());
       
  1738             else if (md->isTypedef())
       
  1739               ol.docify(" typedef");
       
  1740             else if (md->isFriend() && !strcmp(md->typeString(),"friend class"))
       
  1741               ol.docify(" class");
       
  1742             //ol.writeString("\n");
       
  1743           }
       
  1744           ol.writeString("</td>");
       
  1745           memberWritten=TRUE;
       
  1746         }
       
  1747         else if (!Config_getBool("HIDE_UNDOC_MEMBERS") && 
       
  1748                   (md->protection()!=Private || Config_getBool("EXTRACT_PRIVATE") || md->isFriend()) 
       
  1749                 ) // no documentation, 
       
  1750                   // generate link to the class instead.
       
  1751         {
       
  1752           //ol.writeListItem();
       
  1753           ol.writeString("  <tr bgcolor=\"#f0f0f0\"><td>");
       
  1754           if (cd->isObjectiveC())
       
  1755           {
       
  1756             if (md->isObjCMethod())
       
  1757             {
       
  1758               if (md->isStatic())
       
  1759                 ol.writeString("+&nbsp;</td><td>");
       
  1760               else
       
  1761                 ol.writeString("-&nbsp;</td><td>");
       
  1762             }
       
  1763             else
       
  1764               ol.writeString("</td><td>");
       
  1765           }
       
  1766           ol.startBold();
       
  1767           ol.docify(md->name());
       
  1768           ol.endBold();
       
  1769           if (!md->isObjCMethod())
       
  1770           {
       
  1771             if ( md->isFunction() || md->isSignal() || md->isSlot() ) 
       
  1772               ol.docify(md->argsString());
       
  1773             else if (md->isEnumerate())
       
  1774               ol.parseText(" "+theTranslator->trEnumName());
       
  1775             else if (md->isEnumValue())
       
  1776               ol.parseText(" "+theTranslator->trEnumValue());
       
  1777             else if (md->isTypedef())
       
  1778               ol.docify(" typedef");
       
  1779           }
       
  1780           ol.writeString(" (");
       
  1781           ol.parseText(theTranslator->trDefinedIn()+" ");
       
  1782           if (cd->isLinkable())
       
  1783           {
       
  1784             ol.writeObjectLink(
       
  1785                 cd->getReference(),
       
  1786                 cd->getOutputFileBase(),
       
  1787                 0,
       
  1788                 cd->displayName());
       
  1789           }
       
  1790           else
       
  1791           {
       
  1792             ol.startBold();
       
  1793             ol.docify(cd->displayName());
       
  1794             ol.endBold();
       
  1795           }
       
  1796           ol.writeString(")");
       
  1797           ol.writeString("</td>");
       
  1798           memberWritten=TRUE;
       
  1799         }
       
  1800         if (memberWritten)
       
  1801         {
       
  1802           ol.writeString("<td>");
       
  1803           ol.writeObjectLink(cd->getReference(),
       
  1804                              cd->getOutputFileBase(),
       
  1805                              0,
       
  1806                              md->category() ? 
       
  1807                                 md->category()->displayName() : 
       
  1808                                 cd->displayName());
       
  1809           ol.writeString("</td>");
       
  1810           ol.writeString("<td>");
       
  1811         }
       
  1812         if (
       
  1813             (prot!=Public || (virt!=Normal && !m_impl->isObjC) || 
       
  1814              md->isFriend() || md->isRelated() || md->isExplicit() ||
       
  1815              md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) ||
       
  1816              md->isSignal() || md->isSlot() ||
       
  1817              md->isStatic() || vhdlOpt
       
  1818             )
       
  1819             && memberWritten)
       
  1820         {
       
  1821           ol.startTypewriter();
       
  1822           ol.docify(" [");
       
  1823           QStrList sl;
       
  1824           if (vhdlOpt) sl.append(VhdlDocGen::trVhdlType(
       
  1825                           md->getMemberSpecifiers())); //append vhdl type
       
  1826           else if (md->isFriend()) sl.append("friend");
       
  1827           else if (md->isRelated()) sl.append("related");
       
  1828           else
       
  1829           {
       
  1830             if (Config_getBool("INLINE_INFO") && md->isInline())        
       
  1831                                        sl.append("inline");
       
  1832             if (md->isExplicit())      sl.append("explicit");
       
  1833             if (md->isMutable())       sl.append("mutable");
       
  1834             if (prot==Protected)       sl.append("protected");
       
  1835             else if (prot==Private)    sl.append("private");
       
  1836             else if (prot==Package)    sl.append("package");
       
  1837             if (virt==Virtual && 
       
  1838                 !m_impl->isObjC)             sl.append("virtual");
       
  1839             else if (virt==Pure)       sl.append("pure virtual");
       
  1840             if (md->isStatic())        sl.append("static");
       
  1841             if (md->isSignal())        sl.append("signal");
       
  1842             if (md->isSlot())          sl.append("slot");
       
  1843           }
       
  1844           const char *s=sl.first();
       
  1845           while (s)
       
  1846           {
       
  1847             ol.docify(s);
       
  1848             s=sl.next();
       
  1849             if (s) ol.docify(", ");
       
  1850           }
       
  1851           ol.docify("]");
       
  1852           ol.endTypewriter();
       
  1853         }
       
  1854         if (memberWritten)
       
  1855         {
       
  1856           ol.writeString("</td>");
       
  1857           ol.writeString("</tr>\n");
       
  1858         }
       
  1859       }
       
  1860       mi=mni->next();
       
  1861     }
       
  1862   }
       
  1863   //ol.endItemList();
       
  1864 
       
  1865   ol.writeString("</table>");
       
  1866   
       
  1867   endFile(ol);
       
  1868   ol.popGeneratorState();
       
  1869 }
       
  1870 
       
  1871 
       
  1872 // add a reference to an example
       
  1873 bool ClassDef::addExample(const char *anchor,const char *nameStr,
       
  1874     const char *file)
       
  1875 {
       
  1876   if (m_impl->exampleSDict==0)
       
  1877   {
       
  1878     m_impl->exampleSDict = new ExampleSDict;
       
  1879     m_impl->exampleSDict->setAutoDelete(TRUE);
       
  1880   }
       
  1881   if (!m_impl->exampleSDict->find(nameStr))
       
  1882   {
       
  1883     Example *e=new Example;
       
  1884     e->anchor=anchor;
       
  1885     e->name=nameStr;
       
  1886     e->file=file;
       
  1887     m_impl->exampleSDict->inSort(nameStr,e);
       
  1888     return TRUE;
       
  1889   }
       
  1890   return FALSE;
       
  1891 }
       
  1892 
       
  1893 // returns TRUE if this class is used in an example
       
  1894 bool ClassDef::hasExamples()
       
  1895 {
       
  1896   if (m_impl->exampleSDict==0) 
       
  1897     return FALSE;
       
  1898   else
       
  1899     return m_impl->exampleSDict->count()>0;
       
  1900 }
       
  1901 
       
  1902 
       
  1903 void ClassDef::setTemplateArguments(ArgumentList *al)
       
  1904 {
       
  1905   if (al==0) return;
       
  1906   if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
       
  1907   m_impl->tempArgs=new ArgumentList; 
       
  1908   ArgumentListIterator ali(*al);
       
  1909   Argument *a;
       
  1910   for (;(a=ali.current());++ali)
       
  1911   {
       
  1912     m_impl->tempArgs->append(new Argument(*a));
       
  1913   }
       
  1914 }
       
  1915 
       
  1916 void ClassDef::setTypeConstraints(ArgumentList *al)
       
  1917 {
       
  1918   if (al==0) return;
       
  1919   if (!m_impl->typeConstraints) delete m_impl->typeConstraints;
       
  1920   m_impl->typeConstraints = new ArgumentList;
       
  1921   ArgumentListIterator ali(*al);
       
  1922   Argument *a;
       
  1923   for (;(a=ali.current());++ali)
       
  1924   {
       
  1925     m_impl->typeConstraints->append(new Argument(*a));
       
  1926   }
       
  1927 }
       
  1928 
       
  1929 /*! Returns \c TRUE iff this class or a class inheriting from this class
       
  1930  *  is \e not defined in an external tag file. 
       
  1931  */
       
  1932 bool ClassDef::hasNonReferenceSuperClass()
       
  1933 {
       
  1934   bool found=!isReference() && isLinkableInProject() && !isHidden(); 
       
  1935   if (found) 
       
  1936   {
       
  1937     return TRUE; // we're done if this class is not a reference
       
  1938   }
       
  1939   if (m_impl->inheritedBy)
       
  1940   {
       
  1941     BaseClassListIterator bcli(*m_impl->inheritedBy);
       
  1942     for ( ; bcli.current() && !found ; ++bcli ) // for each super class
       
  1943     {
       
  1944       ClassDef *bcd=bcli.current()->classDef;
       
  1945       // recurse into the super class branch
       
  1946       found = found || bcd->hasNonReferenceSuperClass(); 
       
  1947       if (!found)
       
  1948       {
       
  1949         // look for template instances that might have non-reference super classes
       
  1950         QDict<ClassDef> *cil = bcd->getTemplateInstances();
       
  1951         if (cil)
       
  1952         {
       
  1953           QDictIterator<ClassDef> tidi(*cil);
       
  1954           for ( ; tidi.current() && !found ; ++tidi) // for each template instance
       
  1955           {
       
  1956             // recurse into the template instance branch
       
  1957             found = found || tidi.current()->hasNonReferenceSuperClass();
       
  1958           }
       
  1959         }
       
  1960       }
       
  1961     }
       
  1962   }
       
  1963   return found;
       
  1964 }
       
  1965 
       
  1966 /*! called from MemberDef::writeDeclaration() to (recusively) write the 
       
  1967  *  definition of an annonymous struct, union or class.
       
  1968  */
       
  1969 void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup)
       
  1970 {
       
  1971   //ol.insertMemberAlign();
       
  1972   //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup);
       
  1973 
       
  1974   //if (inGroup && md && md->getClassDef()==this) return;
       
  1975 
       
  1976   ol.docify(compoundTypeString());
       
  1977   int ri=name().findRev("::");
       
  1978   if (ri==-1) ri=name().length();
       
  1979   QCString cn=name().right(name().length()-ri-2);
       
  1980   if (!cn.isEmpty() && cn.at(0)!='@' && md)
       
  1981   { 
       
  1982     ol.docify(" ");
       
  1983     if (isLinkable())
       
  1984     {
       
  1985       ol.writeObjectLink(0,0,md->anchor(),cn);
       
  1986     }
       
  1987     else
       
  1988     {
       
  1989       ol.startBold();
       
  1990       ol.docify(cn);
       
  1991       ol.endBold();
       
  1992     }
       
  1993   }
       
  1994   ol.docify(" {");
       
  1995   ol.endMemberItem(); 
       
  1996 
       
  1997   // write user defined member groups
       
  1998   if (m_impl->memberGroupSDict)
       
  1999   {
       
  2000     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
  2001     MemberGroup *mg;
       
  2002     for (;(mg=mgli.current());++mgli)
       
  2003     {
       
  2004       mg->setInGroup(inGroup);
       
  2005       mg->writePlainDeclarations(ol,this,0,0,0);
       
  2006     }
       
  2007   }
       
  2008 
       
  2009   writePlainMemberDeclaration(ol,MemberList::pubTypes,inGroup);
       
  2010   writePlainMemberDeclaration(ol,MemberList::pubMethods,inGroup);
       
  2011   writePlainMemberDeclaration(ol,MemberList::pubAttribs,inGroup);
       
  2012   writePlainMemberDeclaration(ol,MemberList::pubSlots,inGroup);
       
  2013   writePlainMemberDeclaration(ol,MemberList::signals,inGroup);
       
  2014   writePlainMemberDeclaration(ol,MemberList::dcopMethods,inGroup);
       
  2015   writePlainMemberDeclaration(ol,MemberList::properties,inGroup);
       
  2016   writePlainMemberDeclaration(ol,MemberList::events,inGroup);
       
  2017   writePlainMemberDeclaration(ol,MemberList::pubStaticMethods,inGroup);
       
  2018   writePlainMemberDeclaration(ol,MemberList::pubStaticAttribs,inGroup);
       
  2019   writePlainMemberDeclaration(ol,MemberList::proTypes,inGroup);
       
  2020   writePlainMemberDeclaration(ol,MemberList::proMethods,inGroup);
       
  2021   writePlainMemberDeclaration(ol,MemberList::proAttribs,inGroup);
       
  2022   writePlainMemberDeclaration(ol,MemberList::proSlots,inGroup);
       
  2023   writePlainMemberDeclaration(ol,MemberList::proStaticMethods,inGroup);
       
  2024   writePlainMemberDeclaration(ol,MemberList::proStaticAttribs,inGroup);
       
  2025   writePlainMemberDeclaration(ol,MemberList::pacTypes,inGroup);
       
  2026   writePlainMemberDeclaration(ol,MemberList::pacMethods,inGroup);
       
  2027   writePlainMemberDeclaration(ol,MemberList::pacAttribs,inGroup);
       
  2028   writePlainMemberDeclaration(ol,MemberList::pacStaticMethods,inGroup);
       
  2029   writePlainMemberDeclaration(ol,MemberList::pacStaticAttribs,inGroup);
       
  2030   if (Config_getBool("EXTRACT_PRIVATE"))
       
  2031   {
       
  2032     writePlainMemberDeclaration(ol,MemberList::priTypes,inGroup);
       
  2033     writePlainMemberDeclaration(ol,MemberList::priMethods,inGroup);
       
  2034     writePlainMemberDeclaration(ol,MemberList::priAttribs,inGroup);
       
  2035     writePlainMemberDeclaration(ol,MemberList::priSlots,inGroup);
       
  2036     writePlainMemberDeclaration(ol,MemberList::priStaticMethods,inGroup);
       
  2037     writePlainMemberDeclaration(ol,MemberList::priStaticAttribs,inGroup);
       
  2038   }
       
  2039   writePlainMemberDeclaration(ol,MemberList::friends,inGroup);
       
  2040   writePlainMemberDeclaration(ol,MemberList::related,inGroup);
       
  2041 }
       
  2042 
       
  2043 /*! a link to this class is possible within this project */
       
  2044 bool ClassDef::isLinkableInProject() const
       
  2045 { 
       
  2046   static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
       
  2047   static bool extractLocal   = Config_getBool("EXTRACT_LOCAL_CLASSES");
       
  2048   static bool extractStatic  = Config_getBool("EXTRACT_STATIC");
       
  2049   static bool hideUndoc      = Config_getBool("HIDE_UNDOC_CLASSES");
       
  2050   if (m_impl->templateMaster)
       
  2051   {
       
  2052     return m_impl->templateMaster->isLinkableInProject();
       
  2053   }
       
  2054   else
       
  2055   {
       
  2056     return !name().isEmpty() &&                    /* has a name */
       
  2057       !isArtificial() && !isHidden() &&            /* not hidden */
       
  2058       name().find('@')==-1 &&                      /* not anonymous */
       
  2059       (m_impl->prot!=Private || extractPrivate) && /* private */
       
  2060       (!m_impl->isLocal      || extractLocal)   && /* local */
       
  2061       (hasDocumentation()    || !hideUndoc)     && /* documented */ 
       
  2062       (!m_impl->isStatic     || extractStatic)  && /* static */
       
  2063       !isReference();                 /* not an external reference */
       
  2064   }
       
  2065 }
       
  2066 
       
  2067 bool ClassDef::isLinkable() const
       
  2068 {
       
  2069   if (m_impl->templateMaster)
       
  2070   {
       
  2071     return m_impl->templateMaster->isLinkable();
       
  2072   }
       
  2073   else
       
  2074   {
       
  2075     return isLinkableInProject() || isReference();
       
  2076   }
       
  2077 }
       
  2078 
       
  2079 
       
  2080 /*! the class is visible in a class diagram, or class hierarchy */
       
  2081 bool ClassDef::isVisibleInHierarchy() 
       
  2082 { 
       
  2083   static bool allExternals     = Config_getBool("ALLEXTERNALS");
       
  2084   static bool extractPrivate   = Config_getBool("EXTRACT_PRIVATE");
       
  2085   static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
       
  2086   static bool extractStatic    = Config_getBool("EXTRACT_STATIC");
       
  2087 
       
  2088   return // show all classes or a subclass is visible
       
  2089       (allExternals || hasNonReferenceSuperClass()) &&
       
  2090       // and not an annonymous compound
       
  2091       name().find('@')==-1 &&
       
  2092       // not an artifically introduced class
       
  2093       !isArtificial() &&
       
  2094       // and not privately inherited
       
  2095       (m_impl->prot!=Private || extractPrivate) &&
       
  2096       // documented or shown anyway or documentation is external 
       
  2097       (hasDocumentation() || 
       
  2098        !hideUndocClasses || 
       
  2099        (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) || 
       
  2100        isReference()
       
  2101       ) &&
       
  2102       // is not part of an unnamed namespace or shown anyway
       
  2103       (!m_impl->isStatic || extractStatic);
       
  2104 }
       
  2105 
       
  2106 bool ClassDef::hasDocumentation() const
       
  2107 {
       
  2108   return Definition::hasDocumentation();
       
  2109 }
       
  2110 
       
  2111 //----------------------------------------------------------------------
       
  2112 // recursive function:
       
  2113 // returns TRUE iff class definition `bcd' represents an (in)direct base 
       
  2114 // class of class definition `cd'.
       
  2115 
       
  2116 bool ClassDef::isBaseClass(ClassDef *bcd, bool followInstances,int level)
       
  2117 {
       
  2118   bool found=FALSE;
       
  2119   //printf("isBaseClass(cd=%s) looking for %s\n",cd->name().data(),bcd->name().data());
       
  2120   if (level>256)
       
  2121   {
       
  2122     err("Possible recursive class relation while inside %s and looking for %s\n",name().data(),bcd->name().data());
       
  2123     abort();
       
  2124     return FALSE;
       
  2125   }
       
  2126   if (baseClasses())
       
  2127   {
       
  2128     BaseClassListIterator bcli(*baseClasses());
       
  2129     for ( ; bcli.current() && !found ; ++bcli)
       
  2130     {
       
  2131       ClassDef *ccd=bcli.current()->classDef;
       
  2132       if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
       
  2133       //printf("isBaseClass() baseclass %s\n",ccd->name().data());
       
  2134       if (ccd==bcd) 
       
  2135         found=TRUE;
       
  2136       else 
       
  2137         found=ccd->isBaseClass(bcd,followInstances,level+1);
       
  2138     }
       
  2139   }
       
  2140   return found;
       
  2141 }
       
  2142 
       
  2143 //----------------------------------------------------------------------------
       
  2144 
       
  2145 static bool isStandardFunc(MemberDef *md)
       
  2146 {
       
  2147   return md->name()=="operator=" || // assignment operator
       
  2148          md->isConstructor() ||     // constructor
       
  2149          md->isDestructor();        // destructor
       
  2150 }
       
  2151 
       
  2152 /*! 
       
  2153  * recusively merges the `all members' lists of a class base 
       
  2154  * with that of this class. Must only be called for classes without
       
  2155  * subclasses!
       
  2156  */
       
  2157 void ClassDef::mergeMembers()
       
  2158 {
       
  2159   if (m_impl->membersMerged) return;
       
  2160 
       
  2161   static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
       
  2162   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
  2163   QCString sep="::";
       
  2164   if (optimizeOutputForJava || vhdlOpt) sep=".";
       
  2165   int sepLen = sep.length();
       
  2166 
       
  2167   m_impl->membersMerged=TRUE;
       
  2168   //printf("  mergeMembers for %s\n",name().data());
       
  2169   bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB" );
       
  2170   if (baseClasses())
       
  2171   {
       
  2172     //printf("  => has base classes!\n");
       
  2173     BaseClassListIterator bcli(*baseClasses());
       
  2174     BaseClassDef *bcd;
       
  2175     for ( ; (bcd=bcli.current()) ; ++bcli )
       
  2176     {
       
  2177       ClassDef *bClass=bcd->classDef; 
       
  2178 
       
  2179       // merge the members in the base class of this inheritance branch first
       
  2180       bClass->mergeMembers();
       
  2181 
       
  2182       MemberNameInfoSDict *srcMnd  = bClass->memberNameInfoSDict();
       
  2183       MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
       
  2184 
       
  2185       if (srcMnd)
       
  2186       {
       
  2187         MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
       
  2188         MemberNameInfo *srcMni;
       
  2189         for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
       
  2190         {
       
  2191           //printf("    Base member name %s\n",srcMni->memberName());
       
  2192           MemberNameInfo *dstMni;
       
  2193           if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName())))
       
  2194             // a member with that name is already in the class.
       
  2195             // the member may hide or reimplement the one in the sub class
       
  2196             // or there may be another path to the base class that is already 
       
  2197             // visited via another branch in the class hierarchy.
       
  2198           {
       
  2199             MemberNameInfoIterator srcMnii(*srcMni); 
       
  2200             MemberInfo *srcMi;
       
  2201             for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
       
  2202             {
       
  2203               MemberDef *srcMd = srcMi->memberDef;
       
  2204               bool found=FALSE;
       
  2205               bool ambigue=FALSE;
       
  2206               bool hidden=FALSE;
       
  2207               MemberNameInfoIterator dstMnii(*dstMni); 
       
  2208               MemberInfo *dstMi;
       
  2209               ClassDef *srcCd = srcMd->getClassDef();
       
  2210               for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
       
  2211               {
       
  2212                 MemberDef *dstMd = dstMi->memberDef;
       
  2213                 if (srcMd!=dstMd) // different members
       
  2214                 {
       
  2215                   ClassDef *dstCd = dstMd->getClassDef();
       
  2216                   //printf("  Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data());
       
  2217                   if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) 
       
  2218                     // member is in the same or a base class
       
  2219                   {
       
  2220                     LockingPtr<ArgumentList> srcAl = srcMd->argumentList();
       
  2221                     LockingPtr<ArgumentList> dstAl = dstMd->argumentList();
       
  2222                     found=matchArguments2(
       
  2223                         srcMd->getOuterScope(),srcMd->getFileDef(),srcAl.pointer(),
       
  2224                         dstMd->getOuterScope(),dstMd->getFileDef(),dstAl.pointer(),
       
  2225                         TRUE
       
  2226                         );
       
  2227                     //printf("  Yes, matching (%s<->%s): %d\n",
       
  2228                     //    argListToString(srcMd->argumentList()).data(),
       
  2229                     //    argListToString(dstMd->argumentList()).data(),
       
  2230                     //    found);
       
  2231                     hidden = hidden  || !found;
       
  2232                   }
       
  2233                   else // member is in a non base class => multiple inheritance
       
  2234                     // using the same base class.
       
  2235                   {
       
  2236                     //printf("$$ Existing member %s %s add scope %s\n",
       
  2237                     //    dstMi->ambiguityResolutionScope.data(),
       
  2238                     //    dstMd->name().data(),
       
  2239                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
       
  2240 
       
  2241                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
       
  2242                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
       
  2243                       dstMi->ambiguityResolutionScope.prepend(scope);
       
  2244                     ambigue=TRUE;
       
  2245                   }
       
  2246                 }
       
  2247                 else // same members
       
  2248                 {
       
  2249                   // do not add if base class is virtual or 
       
  2250                   // if scope paths are equal or
       
  2251                   // if base class is an interface (and thus implicitly virtual).
       
  2252                   //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt);
       
  2253                   if ((srcMi->virt!=Normal && dstMi->virt!=Normal) ||
       
  2254                       bClass->name()+sep+srcMi->scopePath == dstMi->scopePath ||
       
  2255                       dstMd->getClassDef()->compoundType()==Interface
       
  2256                      ) 
       
  2257                   {
       
  2258                     found=TRUE;
       
  2259                   }
       
  2260                   else // member can be reached via multiple paths in the 
       
  2261                     // inheritance tree
       
  2262                   {
       
  2263                     //printf("$$ Existing member %s %s add scope %s\n",
       
  2264                     //    dstMi->ambiguityResolutionScope.data(),
       
  2265                     //    dstMd->name().data(),
       
  2266                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
       
  2267 
       
  2268                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
       
  2269                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
       
  2270                     {
       
  2271                       dstMi->ambiguityResolutionScope.prepend(scope);
       
  2272                     }
       
  2273                     ambigue=TRUE;
       
  2274                   }
       
  2275                 }
       
  2276               }
       
  2277               //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n",
       
  2278               //    srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass);
       
  2279 
       
  2280               // TODO: fix the case where a member is hidden by inheritance
       
  2281               //       of a member with the same name but with another prototype,
       
  2282               //       while there is more than one path to the member in the 
       
  2283               //       base class due to multiple inheritance. In this case
       
  2284               //       it seems that the member is not reachable by prefixing a 
       
  2285               //       scope name either (according to my compiler). Currently, 
       
  2286               //       this case is shown anyway.
       
  2287               if (!found && srcMd->protection()!=Private)
       
  2288               {
       
  2289                 Protection prot=srcMd->protection();
       
  2290                 if (bcd->prot==Protected && prot==Public)       prot=bcd->prot;
       
  2291                 else if (bcd->prot==Private)                    prot=bcd->prot;
       
  2292 
       
  2293                 if (inlineInheritedMembers)
       
  2294                 {
       
  2295                   if (!isStandardFunc(srcMd))
       
  2296                   {
       
  2297                     //printf("    insertMember `%s'\n",srcMd->name().data());
       
  2298                     internalInsertMember(srcMd,prot,FALSE);
       
  2299                   }
       
  2300                 }
       
  2301 
       
  2302                 Specifier virt=srcMi->virt;
       
  2303                 if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
       
  2304 
       
  2305                 MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE);
       
  2306                 newMi->scopePath=bClass->name()+sep+srcMi->scopePath;
       
  2307                 if (ambigue)
       
  2308                 {
       
  2309                   //printf("$$ New member %s %s add scope %s::\n",
       
  2310                   //     srcMi->ambiguityResolutionScope.data(),
       
  2311                   //     srcMd->name().data(),
       
  2312                   //     bClass->name().data());
       
  2313 
       
  2314                   QCString scope=bClass->name()+sep;
       
  2315                   if (scope!=srcMi->ambiguityResolutionScope.left(scope.length()))
       
  2316                   {
       
  2317                     newMi->ambiguityResolutionScope=
       
  2318                       scope+srcMi->ambiguityResolutionScope.copy();
       
  2319                   }
       
  2320                 }
       
  2321                 if (hidden)
       
  2322                 {
       
  2323                   if (srcMi->ambigClass==0)
       
  2324                   {
       
  2325                     newMi->ambigClass=bClass;
       
  2326                     newMi->ambiguityResolutionScope=bClass->name()+sep;
       
  2327                   }
       
  2328                   else
       
  2329                   {
       
  2330                     newMi->ambigClass=srcMi->ambigClass;
       
  2331                     newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep;
       
  2332                   }
       
  2333                 }
       
  2334                 dstMni->append(newMi);
       
  2335               }
       
  2336             }
       
  2337           }
       
  2338           else // base class has a member that is not in the sub class => copy
       
  2339           {
       
  2340             // create a deep copy of the list (only the MemberInfo's will be 
       
  2341             // copied, not the actual MemberDef's)
       
  2342             MemberNameInfo *newMni = 0;
       
  2343             newMni = new MemberNameInfo(srcMni->memberName()); 
       
  2344 
       
  2345             // copy the member(s) from the base to the sub class
       
  2346             MemberNameInfoIterator mnii(*srcMni);
       
  2347             MemberInfo *mi;
       
  2348             for (;(mi=mnii.current());++mnii)
       
  2349             {
       
  2350               Protection prot = mi->prot;
       
  2351               if (bcd->prot==Protected)
       
  2352               {
       
  2353                 if (prot==Public) prot=Protected;
       
  2354               }
       
  2355               else if (bcd->prot==Private)
       
  2356               {
       
  2357                 prot=Private;
       
  2358               }
       
  2359               //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n",
       
  2360               //    name().data(),mi->memberDef->name().data(),mi->prot,
       
  2361               //    bcd->prot,prot);
       
  2362 
       
  2363               if (mi->prot!=Private)
       
  2364               {
       
  2365                 Specifier virt=mi->virt;
       
  2366                 if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
       
  2367 
       
  2368                 if (inlineInheritedMembers)
       
  2369                 {
       
  2370                   if (!isStandardFunc(mi->memberDef))
       
  2371                   {
       
  2372                     //printf("    insertMember `%s'\n",mi->memberDef->name().data());
       
  2373                     internalInsertMember(mi->memberDef,prot,FALSE);
       
  2374                   }
       
  2375                 }
       
  2376                 //printf("Adding!\n");
       
  2377                 MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE);
       
  2378                 newMi->scopePath=bClass->name()+sep+mi->scopePath;
       
  2379                 newMi->ambigClass=mi->ambigClass;
       
  2380                 newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
       
  2381                 newMni->append(newMi);
       
  2382               }
       
  2383             }
       
  2384 
       
  2385             if (dstMnd==0)
       
  2386             {
       
  2387               m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
       
  2388               m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
       
  2389               dstMnd = m_impl->allMemberNameInfoSDict;
       
  2390             }
       
  2391             // add it to the dictionary
       
  2392             dstMnd->append(newMni->memberName(),newMni);
       
  2393           }
       
  2394         }
       
  2395       }
       
  2396     }
       
  2397   }
       
  2398   //printf("  end mergeMembers\n");
       
  2399 }
       
  2400 
       
  2401 //----------------------------------------------------------------------------
       
  2402 
       
  2403 /*! Merges the members of a Objective-C category into this class.
       
  2404  */
       
  2405 void ClassDef::mergeCategory(ClassDef *category)
       
  2406 {
       
  2407   category->setCategoryOf(this);
       
  2408   category->setArtificial(TRUE);
       
  2409     
       
  2410   MemberNameInfoSDict *srcMnd  = category->memberNameInfoSDict();
       
  2411   MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
       
  2412 
       
  2413   if (srcMnd && dstMnd)
       
  2414   {
       
  2415     MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
       
  2416     MemberNameInfo *srcMni;
       
  2417     for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
       
  2418     {
       
  2419       MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName());
       
  2420       if (dstMni) // method is already defined in the class
       
  2421       {
       
  2422         // TODO: we should remove the other member and insert this one.
       
  2423       }
       
  2424       else // new method name
       
  2425       {
       
  2426         // create a deep copy of the list
       
  2427         MemberNameInfo *newMni = 0;
       
  2428         newMni = new MemberNameInfo(srcMni->memberName()); 
       
  2429 
       
  2430         // copy the member(s) from the category to this class
       
  2431         MemberNameInfoIterator mnii(*srcMni);
       
  2432         MemberInfo *mi;
       
  2433         for (;(mi=mnii.current());++mnii)
       
  2434         {
       
  2435           //printf("Adding '%s'\n",mi->memberDef->name().data());
       
  2436           MemberInfo *newMi=new MemberInfo(mi->memberDef,mi->prot,mi->virt,mi->inherited);
       
  2437           newMi->scopePath=mi->scopePath;
       
  2438           newMi->ambigClass=mi->ambigClass;
       
  2439           newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope;
       
  2440           newMni->append(newMi);
       
  2441           mi->memberDef->moveTo(this);
       
  2442           mi->memberDef->setCategory(category);
       
  2443           internalInsertMember(mi->memberDef,mi->prot,FALSE);
       
  2444         }
       
  2445 
       
  2446         // add it to the dictionary
       
  2447         dstMnd->append(newMni->memberName(),newMni);
       
  2448       }
       
  2449     }
       
  2450   }
       
  2451 }
       
  2452 
       
  2453 //----------------------------------------------------------------------------
       
  2454 
       
  2455 void ClassDef::addUsedClass(ClassDef *cd,const char *accessName)
       
  2456 {
       
  2457   //printf("%s::addUsedClass(%s,%s)\n",name().data(),cd->name().data(),accessName);
       
  2458   if (m_impl->usesImplClassDict==0) 
       
  2459   {
       
  2460     m_impl->usesImplClassDict = new UsesClassDict(17); 
       
  2461     m_impl->usesImplClassDict->setAutoDelete(TRUE);
       
  2462   }
       
  2463   UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
       
  2464   if (ucd==0)
       
  2465   {
       
  2466      ucd = new UsesClassDef(cd);
       
  2467      m_impl->usesImplClassDict->insert(cd->name(),ucd);
       
  2468      //printf("Adding used class %s to class %s\n",
       
  2469      //    cd->name().data(),name().data());
       
  2470   }
       
  2471   ucd->addAccessor(accessName);
       
  2472 }
       
  2473 
       
  2474 void ClassDef::addUsedByClass(ClassDef *cd,const char *accessName)
       
  2475 {
       
  2476   if (m_impl->usedByImplClassDict==0) 
       
  2477   {
       
  2478     m_impl->usedByImplClassDict = new UsesClassDict(17); 
       
  2479     m_impl->usedByImplClassDict->setAutoDelete(TRUE);
       
  2480   }
       
  2481   UsesClassDef *ucd=m_impl->usedByImplClassDict->find(cd->name());
       
  2482   if (ucd==0)
       
  2483   {
       
  2484      ucd = new UsesClassDef(cd);
       
  2485      m_impl->usedByImplClassDict->insert(cd->name(),ucd);
       
  2486      //printf("Adding used by class %s to class %s\n",
       
  2487      //    cd->name().data(),name().data());
       
  2488   }
       
  2489   ucd->addAccessor(accessName);
       
  2490 }
       
  2491 
       
  2492 
       
  2493 #if 0
       
  2494 /*! Builds up a dictionary of all classes that are used by the state of this 
       
  2495  *  class (the "implementation"). 
       
  2496  *  Must be called before mergeMembers() is called!
       
  2497  */
       
  2498 
       
  2499 void ClassDef::determineImplUsageRelation()
       
  2500 {
       
  2501   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
       
  2502   MemberNameInfo *mni;
       
  2503   for (;(mni=mnili.current());++mnili)
       
  2504   {
       
  2505     MemberNameInfoIterator mnii(*mni);
       
  2506     MemberInfo *mi;
       
  2507     for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  2508     {
       
  2509       MemberDef *md=mi->memberDef;
       
  2510       if (md->isVariable()) // for each member variable in this class
       
  2511       {
       
  2512         QCString type=removeRedundantWhiteSpace(md->typeString());
       
  2513         //printf("in class %s found var type=`%s' name=`%s'\n",
       
  2514         //            name().data(),type.data(),md->name().data());
       
  2515         int pos=0;
       
  2516         QCString usedClassName;
       
  2517         QCString templSpec;
       
  2518         bool found=FALSE;
       
  2519         while (extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1 && !found)
       
  2520         {
       
  2521           //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data());
       
  2522           // check if usedClassName is a template argument of its class
       
  2523           ClassDef *cd=md->getClassDef();
       
  2524           if (cd && cd->templateArguments())
       
  2525           {
       
  2526             ArgumentListIterator ali(*cd->templateArguments());
       
  2527             Argument *arg;
       
  2528             int count=0;
       
  2529             for (ali.toFirst();(arg=ali.current());++ali,++count)
       
  2530             {
       
  2531               if (arg->name==usedClassName) // type is a template argument
       
  2532               {
       
  2533                 found=TRUE;
       
  2534                 if (m_impl->usesImplClassDict==0) m_impl->usesImplClassDict = new UsesClassDict(257); 
       
  2535                 cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(),
       
  2536                     usedClassName,ClassDef::Class);
       
  2537                 cd->setIsTemplateBaseClass(count);
       
  2538                 UsesClassDef *ucd = new UsesClassDef(cd);
       
  2539                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
       
  2540                 ucd->templSpecifiers = templSpec;
       
  2541                 ucd->addAccessor(md->name());
       
  2542                 Doxygen::hiddenClasses.append(cd);
       
  2543                 //printf("Adding used template argument %s to class %s\n",
       
  2544                 //    cd->name().data(),name().data());
       
  2545                 //printf("Adding accessor %s to class %s\n",
       
  2546                 //    md->name().data(),ucd->classDef->name().data());
       
  2547               }
       
  2548             }
       
  2549           }
       
  2550 
       
  2551           if (!found)
       
  2552           {
       
  2553             cd=0;
       
  2554             if (getNamespaceDef()!=0)
       
  2555             {
       
  2556               cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec);
       
  2557             }
       
  2558             if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec);
       
  2559             if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try inbetween scopes!
       
  2560             //printf("Search for class %s result=%p\n",usedClassName.data(),cd);
       
  2561             if (cd) // class exists 
       
  2562             {
       
  2563               found=TRUE;
       
  2564               if (m_impl->usesImplClassDict==0) 
       
  2565               {
       
  2566                 m_impl->usesImplClassDict = new UsesClassDict(257); 
       
  2567                 m_impl->usesImplClassDict->setAutoDelete(TRUE);
       
  2568               }
       
  2569               UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
       
  2570               if (ucd==0 || ucd->templSpecifiers!=templSpec)
       
  2571               {
       
  2572                 ucd = new UsesClassDef(cd);
       
  2573                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
       
  2574                 ucd->templSpecifiers = templSpec;
       
  2575                 //printf("Adding used class %s to class %s\n",
       
  2576                 //    cd->name().data(),name().data());
       
  2577               }
       
  2578               ucd->addAccessor(md->name());
       
  2579               //printf("Adding accessor %s to class %s\n",
       
  2580               //    md->name().data(),ucd->classDef->name().data());
       
  2581             }
       
  2582           }
       
  2583         }
       
  2584       }
       
  2585     }
       
  2586   }
       
  2587 #ifdef DUMP
       
  2588   if (m_impl->usesClassDict)
       
  2589   {
       
  2590     msg("Class %s uses the following classes:\n",name().data());
       
  2591     UsesClassDictIterator ucdi(*m_impl->usesClassDict);
       
  2592     UsesClassDef *ucd;
       
  2593     for (;(ucd=ucdi.current());++ucdi)
       
  2594     {
       
  2595       msg("  %s via ",ucd->classDef->name().data());
       
  2596       QDictIterator<void> dvi(*ucd->accessors); 
       
  2597       const char *s;
       
  2598       for (;(s=dvi.currentKey());++dvi)
       
  2599       {
       
  2600         msg("%s ",s);
       
  2601       }
       
  2602       msg("\n");
       
  2603     }
       
  2604   }
       
  2605 #endif
       
  2606 }
       
  2607 
       
  2608 //----------------------------------------------------------------------------
       
  2609 
       
  2610 // I have disabled this code because the graphs it renders quickly become
       
  2611 // too large to be of practical use.
       
  2612 
       
  2613 void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr)
       
  2614 {
       
  2615   QCString type = typeStr;
       
  2616   static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
       
  2617   int p=0,i,l;
       
  2618   while ((i=re.match(type,p,&l))!=-1) // for each class name in the type
       
  2619   {
       
  2620     ClassDef *cd=getClass(name()+"::"+type.mid(i,l));
       
  2621     if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes!
       
  2622     if (cd && cd!=this && !isBaseClass(cd))
       
  2623     {
       
  2624       if (m_impl->usesIntfClassDict==0) 
       
  2625       {
       
  2626         m_impl->usesIntfClassDict = new UsesClassDict(257); 
       
  2627       }
       
  2628       UsesClassDef *ucd=m_impl->usesIntfClassDict->find(cd->name());
       
  2629       if (ucd==0)
       
  2630       {
       
  2631         ucd = new UsesClassDef(cd);
       
  2632         m_impl->usesIntfClassDict->insert(cd->name(),ucd);
       
  2633         //printf("in class `%s' adding used intf class `%s'\n",
       
  2634         //  name().data(),cd->name().data());
       
  2635       }
       
  2636       ucd->addAccessor(md->name());
       
  2637       //printf("in class `%s' adding accessor `%s' to class `%s'\n",
       
  2638       //    name().data(),md->name().data(),ucd->classDef->name().data());
       
  2639     }
       
  2640     p=i+l;
       
  2641   }
       
  2642 }
       
  2643 
       
  2644 void ClassDef::determineIntfUsageRelation()
       
  2645 {
       
  2646   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoList);
       
  2647   MemberNameInfo *mni;
       
  2648   for (;(mni=mnili.current());++mnili)
       
  2649   {
       
  2650     MemberNameInfoIterator mnii(*mni);
       
  2651     MemberInfo *mi;
       
  2652     for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  2653     {
       
  2654       MemberDef *md=mi->memberDef;
       
  2655       
       
  2656       // compute the protection level for this member
       
  2657       Protection protect=md->protection();
       
  2658       if (mi->prot==Protected) // inherited protection
       
  2659       {
       
  2660         if (protect==Public) protect=Protected;
       
  2661         else if (protect==Protected) protect=Private;
       
  2662       }
       
  2663       
       
  2664       if (!md->name().isEmpty() && md->name()[0]!='@' && 
       
  2665           (mi->prot!=Private && protect!=Private)
       
  2666          )
       
  2667       {
       
  2668         // add classes found in the return type
       
  2669         addUsedInterfaceClasses(md,md->typeString());
       
  2670         ArgumentList *al = md->argumentList();
       
  2671         if (al) // member has arguments
       
  2672         {
       
  2673           // add classes found in the types of the argument list
       
  2674           ArgumentListIterator ali(*al);
       
  2675           Argument *a;
       
  2676           for (;(a=ali.current());++ali)
       
  2677           {
       
  2678             if (!a->type.isEmpty() && a->type.at(0)!='@')
       
  2679             {
       
  2680               addUsedInterfaceClasses(md,a->type);
       
  2681             }
       
  2682           }
       
  2683         }
       
  2684       }
       
  2685     }
       
  2686   }
       
  2687 }
       
  2688 #endif
       
  2689 
       
  2690 QCString ClassDef::compoundTypeString() const
       
  2691 {
       
  2692   if (m_impl->compType==Interface && m_impl->isObjC) return "class";
       
  2693   if (Config_getBool("OPTIMIZE_FOR_FORTRAN"))
       
  2694   {
       
  2695     switch (m_impl->compType)
       
  2696     {
       
  2697       case Class:     return "module";
       
  2698       case Struct:    return "type";
       
  2699       case Union:     return "union";
       
  2700       case Interface: return "interface";
       
  2701       case Protocol:  return "protocol";
       
  2702       case Category:  return "category";
       
  2703       case Exception: return "exception";
       
  2704       default:        return "unknown";
       
  2705     } 
       
  2706   }
       
  2707   else
       
  2708   {
       
  2709     switch (m_impl->compType)
       
  2710     {
       
  2711       case Class:     return "class";
       
  2712       case Struct:    return "struct";
       
  2713       case Union:     return "union";
       
  2714       case Interface: return "interface";
       
  2715       case Protocol:  return "protocol";
       
  2716       case Category:  return "category";
       
  2717       case Exception: return "exception";
       
  2718       default:        return "unknown";
       
  2719     }
       
  2720   }
       
  2721 }
       
  2722 
       
  2723 QCString ClassDef::getOutputFileBase() const 
       
  2724 { 
       
  2725   if (m_impl->templateMaster)
       
  2726   {
       
  2727     return m_impl->templateMaster->getOutputFileBase();
       
  2728   }
       
  2729   else if (isReference())
       
  2730   {
       
  2731     return m_impl->fileName;
       
  2732   }
       
  2733   else
       
  2734   {
       
  2735     return convertNameToFile(m_impl->fileName); 
       
  2736   }
       
  2737 }
       
  2738 
       
  2739 QCString ClassDef::getInstanceOutputFileBase() const 
       
  2740 { 
       
  2741   if (isReference())
       
  2742   {
       
  2743     return m_impl->fileName;
       
  2744   }
       
  2745   else
       
  2746   {
       
  2747     return convertNameToFile(m_impl->fileName); 
       
  2748   }
       
  2749 }
       
  2750 
       
  2751 QCString ClassDef::getFileBase() const 
       
  2752 { 
       
  2753   if (m_impl->templateMaster)
       
  2754   {
       
  2755     return m_impl->templateMaster->getFileBase();
       
  2756   }
       
  2757   else
       
  2758   {
       
  2759     return m_impl->fileName; 
       
  2760   }
       
  2761 }
       
  2762 
       
  2763 QCString ClassDef::getSourceFileBase() const 
       
  2764 { 
       
  2765   if (m_impl->templateMaster)
       
  2766   {
       
  2767     return m_impl->templateMaster->getSourceFileBase();
       
  2768   }
       
  2769   else
       
  2770   {
       
  2771     return convertNameToFile(m_impl->fileName)+"_source"; 
       
  2772   }
       
  2773 }
       
  2774 
       
  2775 void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs)
       
  2776 {
       
  2777   gd->addClass(this);
       
  2778   //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data());
       
  2779   if (m_impl->allMemberNameInfoSDict==0) return;
       
  2780   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
       
  2781   MemberNameInfo *mni;
       
  2782   for (;(mni=mnili.current());++mnili)
       
  2783   {
       
  2784     MemberNameInfoIterator mnii(*mni);
       
  2785     MemberInfo *mi;
       
  2786     for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  2787     {
       
  2788       MemberDef *md=mi->memberDef;
       
  2789       md->setGroupDef(gd,pri,fileName,startLine,hasDocs);
       
  2790       gd->insertMember(md,TRUE);
       
  2791       ClassDef *innerClass = md->getClassDefOfAnonymousType();
       
  2792       if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs);
       
  2793     }
       
  2794   }
       
  2795 }
       
  2796 
       
  2797 void ClassDef::addInnerCompound(Definition *d)
       
  2798 {
       
  2799   //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data());
       
  2800   if (d->definitionType()==Definition::TypeClass) // only classes can be
       
  2801                                                   // nested in classes.
       
  2802   {
       
  2803     if (m_impl->innerClasses==0)
       
  2804     {
       
  2805       m_impl->innerClasses = new ClassSDict(17);
       
  2806     }
       
  2807     m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d);
       
  2808   }
       
  2809 }
       
  2810 
       
  2811 Definition *ClassDef::findInnerCompound(const char *name)
       
  2812 {
       
  2813   Definition *result=0;
       
  2814   if (name==0) return 0;
       
  2815   if (m_impl->innerClasses)
       
  2816   {
       
  2817     result = m_impl->innerClasses->find(name);
       
  2818   }
       
  2819   return result;
       
  2820 }
       
  2821 
       
  2822 //void ClassDef::initTemplateMapping()
       
  2823 //{
       
  2824 //  m_impl->templateMapping->clear();
       
  2825 //  ArgumentList *al = templateArguments();
       
  2826 //  if (al)
       
  2827 //  {
       
  2828 //    ArgumentListIterator ali(*al);
       
  2829 //    Argument *arg;
       
  2830 //    for (ali.toFirst();(arg=ali.current());++ali)
       
  2831 //    {
       
  2832 //      setTemplateArgumentMapping(arg->name,arg->defval);
       
  2833 //    }
       
  2834 //  }
       
  2835 //}
       
  2836 //void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual)
       
  2837 //{
       
  2838 //  //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual);
       
  2839 //  if (m_impl->templateMapping && formal)
       
  2840 //  {
       
  2841 //    if (m_impl->templateMapping->find(formal))
       
  2842 //    {
       
  2843 //      m_impl->templateMapping->remove(formal);
       
  2844 //    }
       
  2845 //    m_impl->templateMapping->insert(formal,new QCString(actual));
       
  2846 //  }
       
  2847 //}
       
  2848 //
       
  2849 //QCString ClassDef::getTemplateArgumentMapping(const char *formal) const
       
  2850 //{
       
  2851 //  if (m_impl->templateMapping && formal)
       
  2852 //  {
       
  2853 //    QCString *s = m_impl->templateMapping->find(formal);
       
  2854 //    if (s)
       
  2855 //    {
       
  2856 //      return *s;
       
  2857 //    }
       
  2858 //  }
       
  2859 //  return "";
       
  2860 //}
       
  2861 
       
  2862 ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName,
       
  2863     int startLine, const QCString &templSpec,bool &freshInstance)
       
  2864 {
       
  2865   freshInstance = FALSE;
       
  2866   if (m_impl->templateInstances==0) 
       
  2867   {
       
  2868     m_impl->templateInstances = new QDict<ClassDef>(17);
       
  2869   }
       
  2870   ClassDef *templateClass=m_impl->templateInstances->find(templSpec);
       
  2871   if (templateClass==0)
       
  2872   {
       
  2873     Debug::print(Debug::Classes,0,"      New template instance class `%s'`%s'\n",name().data(),templSpec.data());
       
  2874     templateClass = new ClassDef(
       
  2875         fileName,startLine,localName()+templSpec,ClassDef::Class);
       
  2876     templateClass->setTemplateMaster(this);
       
  2877     templateClass->setOuterScope(getOuterScope());
       
  2878     templateClass->setHidden(isHidden());
       
  2879     m_impl->templateInstances->insert(templSpec,templateClass);
       
  2880     freshInstance=TRUE;
       
  2881   }
       
  2882   return templateClass;
       
  2883 }
       
  2884 
       
  2885 ClassDef *ClassDef::getVariableInstance(const char *templSpec)
       
  2886 {
       
  2887   if (m_impl->variableInstances==0) 
       
  2888   {
       
  2889     m_impl->variableInstances = new QDict<ClassDef>(17);
       
  2890     m_impl->variableInstances->setAutoDelete(TRUE);
       
  2891   }
       
  2892   ClassDef *templateClass=m_impl->variableInstances->find(templSpec);
       
  2893   if (templateClass==0)
       
  2894   {
       
  2895     Debug::print(Debug::Classes,0,"      New template variable instance class `%s'`%s'\n",name().data(),templSpec);
       
  2896     templateClass = new ClassDef("<code>",1,name()+templSpec,
       
  2897                         ClassDef::Class,0,0,FALSE);
       
  2898     templateClass->addMembersToTemplateInstance( this, templSpec );
       
  2899     templateClass->setTemplateMaster(this);
       
  2900     m_impl->variableInstances->insert(templSpec,templateClass);
       
  2901   }
       
  2902   return templateClass;
       
  2903 }
       
  2904 
       
  2905 void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames)
       
  2906 {
       
  2907   if (templateNames==0) return;
       
  2908   if (m_impl->templBaseClassNames==0)
       
  2909   {
       
  2910     m_impl->templBaseClassNames = new QDict<int>(17);
       
  2911     m_impl->templBaseClassNames->setAutoDelete(TRUE);
       
  2912   }
       
  2913   // make a deep copy of the dictionary.
       
  2914   QDictIterator<int> qdi(*templateNames);
       
  2915   for (;qdi.current();++qdi)
       
  2916   {
       
  2917     if (m_impl->templBaseClassNames->find(qdi.currentKey())==0)
       
  2918     {
       
  2919       m_impl->templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current()));
       
  2920     }
       
  2921   }
       
  2922 }
       
  2923 
       
  2924 QDict<int> *ClassDef::getTemplateBaseClassNames() const
       
  2925 {
       
  2926   return m_impl->templBaseClassNames;
       
  2927 }
       
  2928 
       
  2929 void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec)
       
  2930 {
       
  2931   //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec);
       
  2932   if (cd->memberNameInfoSDict()==0) return;
       
  2933   MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict());
       
  2934   MemberNameInfo *mni;
       
  2935   for (;(mni=mnili.current());++mnili)
       
  2936   {
       
  2937     MemberNameInfoIterator mnii(*mni);
       
  2938     MemberInfo *mi;
       
  2939     for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  2940     {
       
  2941       ArgumentList *actualArguments = new ArgumentList;
       
  2942       stringToArgumentList(templSpec,actualArguments);
       
  2943       MemberDef *md = mi->memberDef;
       
  2944       MemberDef *imd = md->createTemplateInstanceMember(
       
  2945                           cd->templateArguments(),actualArguments);
       
  2946       delete actualArguments;
       
  2947       //printf("%s->setMemberClass(%p)\n",imd->name().data(),this);
       
  2948       imd->setMemberClass(this);
       
  2949       imd->setTemplateMaster(md);
       
  2950       imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
       
  2951       imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
       
  2952       imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
       
  2953       imd->setMemberSpecifiers(md->getMemberSpecifiers());
       
  2954       imd->setMemberGroupId(md->getMemberGroupId());
       
  2955       insertMember(imd);
       
  2956       //printf("Adding member=%s %s%s to class %s templSpec %s\n",
       
  2957       //    imd->typeString(),imd->name().data(),imd->argsString(),
       
  2958       //    imd->getClassDef()->name().data(),templSpec);
       
  2959       // insert imd in the list of all members
       
  2960       //printf("Adding member=%s class=%s\n",imd->name().data(),name().data());
       
  2961       MemberName *mn = Doxygen::memberNameSDict->find(imd->name());
       
  2962       if (mn==0)
       
  2963       {
       
  2964         mn = new MemberName(imd->name());
       
  2965         Doxygen::memberNameSDict->append(imd->name(),mn);
       
  2966       }
       
  2967       mn->append(imd);
       
  2968     }
       
  2969   }
       
  2970 }
       
  2971 
       
  2972 QCString ClassDef::getReference() const
       
  2973 {
       
  2974   if (m_impl->templateMaster)
       
  2975   {
       
  2976     return m_impl->templateMaster->getReference();
       
  2977   }
       
  2978   else
       
  2979   {
       
  2980     return Definition::getReference();
       
  2981   }
       
  2982 }
       
  2983 
       
  2984 bool ClassDef::isReference() const
       
  2985 {
       
  2986   if (m_impl->templateMaster)
       
  2987   {
       
  2988     return m_impl->templateMaster->isReference();
       
  2989   }
       
  2990   else
       
  2991   {
       
  2992     return Definition::isReference();
       
  2993   }
       
  2994 }
       
  2995 
       
  2996 void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const
       
  2997 {
       
  2998   Definition *d=getOuterScope();
       
  2999   if (d)
       
  3000   {
       
  3001     if (d->definitionType()==Definition::TypeClass)
       
  3002     {
       
  3003       ClassDef *cd=(ClassDef *)d;
       
  3004       cd->getTemplateParameterLists(lists);
       
  3005     }
       
  3006   }
       
  3007   if (templateArguments())
       
  3008   {
       
  3009     lists.append(templateArguments());
       
  3010   }
       
  3011 }
       
  3012 
       
  3013 QCString ClassDef::qualifiedNameWithTemplateParameters(
       
  3014     QList<ArgumentList> *actualParams) const
       
  3015 {
       
  3016   static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
       
  3017   static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES");
       
  3018   //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data());
       
  3019   QCString scName;
       
  3020   if (!hideScopeNames)
       
  3021   {
       
  3022     Definition *d=getOuterScope();
       
  3023     if (d)
       
  3024     {
       
  3025       if (d->definitionType()==Definition::TypeClass)
       
  3026       {
       
  3027         ClassDef *cd=(ClassDef *)d;
       
  3028         scName = cd->qualifiedNameWithTemplateParameters(actualParams);
       
  3029       }
       
  3030       else
       
  3031       {
       
  3032         scName = d->qualifiedName();
       
  3033       }
       
  3034     }
       
  3035 
       
  3036     QCString scopeSeparator;
       
  3037     if (optimizeOutputJava)
       
  3038       scopeSeparator=".";
       
  3039     else
       
  3040       scopeSeparator="::";
       
  3041 
       
  3042     if (!scName.isEmpty()) scName+=scopeSeparator;
       
  3043   }
       
  3044   scName+=className();
       
  3045   ArgumentList *al=0;
       
  3046   bool isSpecialization = localName().find('<')!=-1;
       
  3047   if (templateArguments())
       
  3048   {
       
  3049     if (actualParams && (al=actualParams->current()))
       
  3050     {
       
  3051       if (!isSpecialization)
       
  3052       {
       
  3053         scName+=tempArgListToString(al);
       
  3054       }
       
  3055       actualParams->next();
       
  3056     }
       
  3057     else
       
  3058     {
       
  3059       if (!isSpecialization)
       
  3060       {
       
  3061         scName+=tempArgListToString(templateArguments());
       
  3062       }
       
  3063     }
       
  3064   }
       
  3065   //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data());
       
  3066   return scName;
       
  3067 }
       
  3068 
       
  3069 QCString ClassDef::className() const
       
  3070 {
       
  3071   if (m_impl->className.isEmpty())
       
  3072   {
       
  3073     return localName();
       
  3074   }
       
  3075   else
       
  3076   {
       
  3077     return m_impl->className;
       
  3078   }
       
  3079 };
       
  3080 
       
  3081 void ClassDef::setClassName(const char *name)
       
  3082 {
       
  3083   m_impl->className = name;
       
  3084 }
       
  3085 
       
  3086 void ClassDef::addListReferences()
       
  3087 {
       
  3088   bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN");
       
  3089   if (!isLinkableInProject()) return;
       
  3090   //printf("ClassDef(%s)::addListReferences()\n",name().data());
       
  3091   {
       
  3092     LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
       
  3093     addRefItem(xrefItems.pointer(),
       
  3094              qualifiedName(),
       
  3095              fortranOpt?theTranslator->trType(TRUE,TRUE):
       
  3096                         theTranslator->trClass(TRUE,TRUE),
       
  3097              getOutputFileBase(),
       
  3098              displayName(),
       
  3099              0
       
  3100             );
       
  3101   }
       
  3102   if (m_impl->memberGroupSDict)
       
  3103   {
       
  3104     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
       
  3105     MemberGroup *mg;
       
  3106     for (;(mg=mgli.current());++mgli)
       
  3107     {
       
  3108       mg->addListReferences(this);
       
  3109     }
       
  3110   }
       
  3111   QListIterator<MemberList> mli(m_impl->memberLists);
       
  3112   MemberList *ml;
       
  3113   for (mli.toFirst();(ml=mli.current());++mli)
       
  3114   {
       
  3115     if (ml->listType()&MemberList::detailedLists)
       
  3116     {
       
  3117       ml->addListReferences(this);
       
  3118     }
       
  3119   }
       
  3120 }
       
  3121 
       
  3122 MemberDef *ClassDef::getMemberByName(const QCString &name) const
       
  3123 {
       
  3124   MemberDef *xmd = 0;
       
  3125   if (m_impl->allMemberNameInfoSDict)
       
  3126   {
       
  3127     MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name);
       
  3128     if (mni)
       
  3129     {
       
  3130       const int maxInheritanceDepth = 100000;
       
  3131       int mdist=maxInheritanceDepth;
       
  3132       MemberNameInfoIterator mnii(*mni);
       
  3133       MemberInfo *mi;
       
  3134       for (mnii.toFirst();(mi=mnii.current());++mnii)
       
  3135       {
       
  3136         ClassDef *mcd=mi->memberDef->getClassDef();
       
  3137         int m=minClassDistance(this,mcd);
       
  3138         //printf("found member in %s linkable=%d m=%d\n",
       
  3139         //    mcd->name().data(),mcd->isLinkable(),m);
       
  3140         if (m<mdist && mcd->isLinkable())
       
  3141         {
       
  3142           mdist=m;
       
  3143           xmd=mi->memberDef;
       
  3144         }
       
  3145       }
       
  3146     }
       
  3147   }
       
  3148   //printf("getMemberByName(%s)=%p\n",name.data(),xmd);
       
  3149   return xmd;
       
  3150 }
       
  3151 
       
  3152 bool ClassDef::isAccessibleMember(MemberDef *md)
       
  3153 {
       
  3154   return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE);
       
  3155 }
       
  3156 
       
  3157 MemberList *ClassDef::createMemberList(MemberList::ListType lt)
       
  3158 {
       
  3159   m_impl->memberLists.setAutoDelete(TRUE);
       
  3160   QListIterator<MemberList> mli(m_impl->memberLists);
       
  3161   MemberList *ml;
       
  3162   for (mli.toFirst();(ml=mli.current());++mli)
       
  3163   {
       
  3164     if (ml->listType()==lt)
       
  3165     {
       
  3166       return ml;
       
  3167     }
       
  3168   }
       
  3169   // not found, create a new member list
       
  3170   ml = new MemberList(lt);
       
  3171   m_impl->memberLists.append(ml);
       
  3172   return ml;
       
  3173 }
       
  3174 
       
  3175 MemberList *ClassDef::getMemberList(MemberList::ListType lt)
       
  3176 {
       
  3177   MemberList *ml = m_impl->memberLists.first();
       
  3178   while (ml)
       
  3179   {
       
  3180     if (ml->listType()==lt)
       
  3181     {
       
  3182       return ml;
       
  3183     }
       
  3184     ml = m_impl->memberLists.next();
       
  3185   }
       
  3186   return 0;
       
  3187 }
       
  3188 
       
  3189 void ClassDef::addMemberToList(MemberList::ListType lt,MemberDef *md,bool isBrief)
       
  3190 {
       
  3191   static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
       
  3192   static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS");
       
  3193   MemberList *ml = createMemberList(lt);
       
  3194   if (( isBrief && sortBriefDocs ) ||
       
  3195       (!isBrief && sortMemberDocs)
       
  3196      )
       
  3197     ml->inSort(md);
       
  3198   else
       
  3199     ml->append(md);
       
  3200 
       
  3201   // for members in the declaration lists we set the section, needed for member grouping
       
  3202   if ((ml->listType()&MemberList::detailedLists)==0) md->setSectionList(this,ml);
       
  3203 }
       
  3204 
       
  3205 void ClassDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title,
       
  3206                const char *subTitle)
       
  3207 {
       
  3208   static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
       
  3209   MemberList * ml = getMemberList(lt);
       
  3210   if (ml) 
       
  3211   {
       
  3212     if (optimizeVhdl) // use specific declarations function
       
  3213     {
       
  3214       VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this,0);
       
  3215     }
       
  3216     else // ise generic declaration function
       
  3217     {
       
  3218       ml->writeDeclarations(ol,this,0,0,0,title,subTitle); 
       
  3219     }
       
  3220   }
       
  3221 }
       
  3222 
       
  3223 void ClassDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title)
       
  3224 {
       
  3225   MemberList * ml = getMemberList(lt);
       
  3226   if (ml) ml->writeDocumentation(ol,name(),this,title);
       
  3227 }
       
  3228 
       
  3229 void ClassDef::writePlainMemberDeclaration(OutputList &ol,MemberList::ListType lt,bool inGroup)
       
  3230 {
       
  3231   MemberList * ml = getMemberList(lt);
       
  3232   if (ml) 
       
  3233   {
       
  3234     ml->setInGroup(inGroup);
       
  3235     ml->writePlainDeclarations(ol,this,0,0,0); 
       
  3236   }
       
  3237 }
       
  3238 
       
  3239 bool ClassDef::isLocal() const 
       
  3240 { 
       
  3241   return m_impl->isLocal; 
       
  3242 }
       
  3243 
       
  3244 ClassSDict *ClassDef::getInnerClasses() 
       
  3245 { 
       
  3246   return m_impl->innerClasses; 
       
  3247 }
       
  3248 
       
  3249 ClassDef::CompoundType ClassDef::compoundType() const 
       
  3250 { 
       
  3251   return m_impl->compType; 
       
  3252 } 
       
  3253 
       
  3254 BaseClassList *ClassDef::baseClasses() const
       
  3255 { 
       
  3256   return m_impl->inherits; 
       
  3257 }
       
  3258 
       
  3259 BaseClassList *ClassDef::subClasses() const
       
  3260 { 
       
  3261   return m_impl->inheritedBy; 
       
  3262 }
       
  3263 
       
  3264 MemberNameInfoSDict *ClassDef::memberNameInfoSDict() const
       
  3265 { 
       
  3266   return m_impl->allMemberNameInfoSDict; 
       
  3267 }
       
  3268 
       
  3269 Protection ClassDef::protection() const 
       
  3270 { 
       
  3271   return m_impl->prot; 
       
  3272 }
       
  3273 
       
  3274 ArgumentList *ClassDef::templateArguments() const 
       
  3275 { 
       
  3276   return m_impl->tempArgs; 
       
  3277 }
       
  3278 
       
  3279 NamespaceDef *ClassDef::getNamespaceDef() const
       
  3280 { 
       
  3281   return m_impl->nspace; 
       
  3282 }
       
  3283 
       
  3284 FileDef *ClassDef::getFileDef() const 
       
  3285 { 
       
  3286   return m_impl->fileDef; 
       
  3287 }
       
  3288 
       
  3289 QDict<ClassDef> *ClassDef::getTemplateInstances() const 
       
  3290 { 
       
  3291   return m_impl->templateInstances; 
       
  3292 }
       
  3293 
       
  3294 ClassDef *ClassDef::templateMaster() const 
       
  3295 { 
       
  3296   return m_impl->templateMaster; 
       
  3297 } 
       
  3298 
       
  3299 bool ClassDef::isTemplate() const 
       
  3300 { 
       
  3301   return m_impl->tempArgs!=0; 
       
  3302 }
       
  3303 
       
  3304 IncludeInfo *ClassDef::includeInfo() const 
       
  3305 { 
       
  3306   return m_impl->incInfo; 
       
  3307 }
       
  3308 
       
  3309 UsesClassDict *ClassDef::usedImplementationClasses() const 
       
  3310 { 
       
  3311   return m_impl->usesImplClassDict; 
       
  3312 }
       
  3313 
       
  3314 UsesClassDict *ClassDef::usedByImplementationClasses() const 
       
  3315 { 
       
  3316   return m_impl->usedByImplClassDict; 
       
  3317 }
       
  3318 
       
  3319 UsesClassDict *ClassDef::usedInterfaceClasses() const
       
  3320 {
       
  3321   return m_impl->usesIntfClassDict;
       
  3322 }
       
  3323 
       
  3324 bool ClassDef::isTemplateArgument() const
       
  3325 {
       
  3326   return m_impl->isTemplArg;
       
  3327 }
       
  3328 
       
  3329 bool ClassDef::isAbstract() const 
       
  3330 { 
       
  3331   return m_impl->isAbstract; 
       
  3332 }
       
  3333 
       
  3334 bool ClassDef::isObjectiveC() const 
       
  3335 { 
       
  3336   return m_impl->isObjC; 
       
  3337 }
       
  3338 
       
  3339 ClassDef *ClassDef::categoryOf() const 
       
  3340 { 
       
  3341   return m_impl->categoryOf; 
       
  3342 }
       
  3343 
       
  3344 const QList<MemberList> &ClassDef::getMemberLists() const 
       
  3345 { 
       
  3346   return m_impl->memberLists; 
       
  3347 }
       
  3348 
       
  3349 MemberGroupSDict *ClassDef::getMemberGroupSDict() const 
       
  3350 { 
       
  3351   return m_impl->memberGroupSDict; 
       
  3352 }
       
  3353 
       
  3354 void ClassDef::setNamespace(NamespaceDef *nd) 
       
  3355 { 
       
  3356   m_impl->nspace = nd; 
       
  3357 }
       
  3358 
       
  3359 void ClassDef::setFileDef(FileDef *fd) 
       
  3360 { 
       
  3361   m_impl->fileDef=fd; 
       
  3362 }
       
  3363 
       
  3364 void ClassDef::setSubGrouping(bool enabled) 
       
  3365 { 
       
  3366   m_impl->subGrouping = enabled; 
       
  3367 }
       
  3368 
       
  3369 void ClassDef::setProtection(Protection p) 
       
  3370 { 
       
  3371   m_impl->prot=p; 
       
  3372 }
       
  3373 
       
  3374 void ClassDef::setIsStatic(bool b) 
       
  3375 { 
       
  3376   m_impl->isStatic=b; 
       
  3377 }
       
  3378 
       
  3379 void ClassDef::setIsObjectiveC(bool b) 
       
  3380 { 
       
  3381   m_impl->isObjC=b; 
       
  3382 }
       
  3383 
       
  3384 void ClassDef::setCompoundType(CompoundType t) 
       
  3385 { 
       
  3386   m_impl->compType = t; 
       
  3387 } 
       
  3388 
       
  3389 void ClassDef::setTemplateMaster(ClassDef *tm) 
       
  3390 { 
       
  3391   m_impl->templateMaster=tm; 
       
  3392 }
       
  3393 
       
  3394 void ClassDef::makeTemplateArgument(bool b) 
       
  3395 { 
       
  3396   m_impl->isTemplArg = b; 
       
  3397 }
       
  3398 
       
  3399 void ClassDef::setCategoryOf(ClassDef *cd)
       
  3400 {
       
  3401   m_impl->categoryOf = cd;
       
  3402 }
       
  3403 
       
  3404 void ClassDef::setUsedOnly(bool b)
       
  3405 {
       
  3406   m_impl->usedOnly = b;
       
  3407 }
       
  3408 
       
  3409 bool ClassDef::isUsedOnly() const
       
  3410 {
       
  3411   return m_impl->usedOnly;
       
  3412 }
       
  3413 
       
  3414 void ClassDef::reclassifyMember(MemberDef *md,MemberDef::MemberType t)
       
  3415 {
       
  3416   md->setMemberType(t);
       
  3417   MemberList *ml = m_impl->memberLists.first();
       
  3418   while (ml)
       
  3419   {
       
  3420     ml->remove(md);
       
  3421     ml = m_impl->memberLists.next();
       
  3422   }
       
  3423   insertMember(md);
       
  3424 }
       
  3425