classdef.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * $Id: classdef.cpp,v 1.54 2001/03/19 19:27:39 root Exp $
00004  *
00005  * Copyright (C) 1997-2008 by Dimitri van Heesch.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and its
00008  * documentation under the terms of the GNU General Public License is hereby 
00009  * granted. No representations are made about the suitability of this software 
00010  * for any purpose. It is provided "as is" without express or implied warranty.
00011  * See the GNU General Public License for more details.
00012  *
00013  * Documents produced by Doxygen are derivative works derived from the
00014  * input used in their production; they are not affected by this license.
00015  *
00016  */
00017 
00018 #include <stdio.h>
00019 #include <qfile.h>
00020 #include <qregexp.h>
00021 #include "classdef.h"
00022 #include "classlist.h"
00023 #include "entry.h"
00024 #include "doxygen.h"
00025 #include "membername.h"
00026 #include "message.h"
00027 #include "config.h"
00028 #include "util.h"
00029 #include "diagram.h"
00030 #include "language.h"
00031 #include "htmlhelp.h"
00032 #include "example.h"
00033 #include "outputlist.h"
00034 #include "dot.h"
00035 #include "defargs.h"
00036 #include "debug.h"
00037 #include "docparser.h"
00038 #include "searchindex.h"
00039 #include "vhdldocgen.h"
00040 
00041 //static inline MemberList *createNewMemberList(MemberList::ListType lt)
00042 //{
00043 //  MemberList *result = new MemberList(lt);
00044 //  return result;
00045 //}
00046 
00047 class ClassDefImpl
00048 {
00049   public:
00050     ClassDefImpl();
00051    ~ClassDefImpl();
00052     void init(const char *defFileName, const char *name,
00053               const QCString &ctStr, const char *fName);
00054 
00059     QCString fileName;                   
00060 
00064     IncludeInfo *incInfo;                
00065 
00069     BaseClassList *inherits;
00070 
00073     BaseClassList *inheritedBy;
00074 
00078     NamespaceDef  *nspace;              
00079 
00081     FileDef *fileDef;
00082 
00084     MemberNameInfoSDict *allMemberNameInfoSDict;
00085 
00087     ArgumentList *tempArgs;
00088 
00090     ArgumentList *typeConstraints;
00091 
00093     QStrList files;
00094 
00096     ExampleSDict *exampleSDict;
00097 
00099     ClassDef::CompoundType compType;
00100 
00105     Protection prot;
00106 
00110     ClassSDict *innerClasses;
00111 
00112     /* classes for the collaboration diagram */
00113     UsesClassDict *usesImplClassDict;
00114     UsesClassDict *usedByImplClassDict;
00115     UsesClassDict *usesIntfClassDict;
00116 
00120     QDict<ClassDef> *templateInstances;
00121 
00126     QDict<ClassDef> *variableInstances;
00127 
00128     QDict<int> *templBaseClassNames;
00129 
00131     ClassDef *templateMaster;
00132 
00134     QCString className;
00135 
00139     ClassDef *categoryOf;
00140 
00141     QList<MemberList> memberLists;
00142 
00143     /* user defined member groups */
00144     MemberGroupSDict *memberGroupSDict;
00145 
00147     bool isAbstract;
00148 
00150     bool isStatic;
00151 
00153     bool isObjC;
00154 
00156     bool membersMerged;
00157 
00159     bool isLocal;
00160 
00161     bool isTemplArg;
00162 
00167     bool subGrouping; 
00168 
00169     bool usedOnly;
00170 };
00171 
00172 void ClassDefImpl::init(const char *defFileName, const char *name,
00173                         const QCString &ctStr, const char *fName)
00174 {
00175   if (fName)
00176   {
00177     fileName=stripExtension(fName);
00178   }
00179   else
00180   {
00181     fileName=ctStr+name;
00182   }
00183   exampleSDict = 0;
00184   inherits    = 0;
00185   inheritedBy = 0;
00186   allMemberNameInfoSDict = 0;
00187   incInfo=0;
00188   tempArgs=0;
00189   typeConstraints=0;
00190   prot=Public;
00191   nspace=0;
00192   fileDef=0;
00193   usesImplClassDict=0;
00194   usedByImplClassDict=0;
00195   usesIntfClassDict=0;
00196   memberGroupSDict = 0;
00197   innerClasses = 0;
00198   subGrouping=Config_getBool("SUBGROUPING");
00199   templateInstances = 0;
00200   variableInstances = 0;
00201   templateMaster =0;
00202   templBaseClassNames = 0;
00203   isAbstract = FALSE;
00204   isStatic = FALSE;
00205   isTemplArg = FALSE;
00206   membersMerged = FALSE;
00207   categoryOf = 0;
00208   usedOnly = FALSE;
00209   QCString ns;
00210   extractNamespaceName(name,className,ns);
00211   //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data());
00212 
00213   if (((QCString)defFileName).right(5)!=".java" && 
00214       guessSection(defFileName)==Entry::SOURCE_SEC)
00215   {
00216     isLocal=TRUE;
00217   }
00218   else
00219   {
00220     isLocal=FALSE;
00221   }
00222 }
00223 
00224 ClassDefImpl::ClassDefImpl()
00225 {
00226 }
00227 
00228 ClassDefImpl::~ClassDefImpl()
00229 {
00230   delete inherits;
00231   delete inheritedBy;
00232   delete allMemberNameInfoSDict;
00233   delete exampleSDict;
00234   delete usesImplClassDict;
00235   delete usedByImplClassDict;
00236   delete usesIntfClassDict;
00237   delete incInfo;
00238   delete memberGroupSDict;
00239   delete innerClasses;
00240   delete templateInstances;
00241   delete variableInstances;
00242   delete templBaseClassNames;
00243   delete tempArgs;
00244   delete typeConstraints;
00245 }
00246 
00247 // constructs a new class definition
00248 ClassDef::ClassDef(
00249     const char *defFileName,int defLine,
00250     const char *nm,CompoundType ct,
00251     const char *lref,const char *fName,
00252     bool isSymbol) 
00253  : Definition(defFileName,defLine,removeRedundantWhiteSpace(nm),0,0,isSymbol) 
00254 {
00255   visited=FALSE;
00256   setReference(lref);
00257   m_impl = new ClassDefImpl;
00258   m_impl->compType = ct;
00259   m_impl->isObjC   = FALSE;
00260   m_impl->init(defFileName,name(),compoundTypeString(),fName);
00261 
00262 }
00263 
00264 // destroy the class definition
00265 ClassDef::~ClassDef()
00266 {
00267   delete m_impl;
00268 }
00269 
00270 QCString ClassDef::getMemberListFileName() const
00271 {
00272   return convertNameToFile(compoundTypeString()+name()+"-members");
00273 }
00274 
00275 QCString ClassDef::displayName() const
00276 {
00277   static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES");
00278   static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
00279   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
00280   QCString n;
00281   if (vhdlOpt)
00282   {
00283     n = VhdlDocGen::getClassName(this);
00284   }
00285   else if (hideScopeNames)
00286   {
00287     n=m_impl->className;
00288   }
00289   else
00290   {
00291     n=qualifiedNameWithTemplateParameters();
00292   }
00293   if (optimizeOutputForJava)
00294   {
00295     n=substitute(n,"::",".");
00296   }
00297   if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p")
00298   {
00299     n="< "+n.left(n.length()-2)+" >";
00300   }
00301   return n;
00302 }
00303 
00304 // inserts a base class in the inheritance list
00305 void ClassDef::insertBaseClass(ClassDef *cd,const char *n,Protection p,
00306                                Specifier s,const char *t)
00307 {
00308   //printf("*** insert base class %s into %s\n",cd->name().data(),name().data());
00309   //inherits->inSort(new BaseClassDef(cd,p,s,t));
00310   if (m_impl->inherits==0)
00311   {
00312     m_impl->inherits = new BaseClassList;
00313     m_impl->inherits->setAutoDelete(TRUE);
00314   }
00315   m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t));
00316 }
00317 
00318 // inserts a sub class in the inherited list
00319 void ClassDef::insertSubClass(ClassDef *cd,Protection p,
00320                                 Specifier s,const char *t)
00321 {
00322   //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data());
00323   if (m_impl->inheritedBy==0)
00324   {
00325     m_impl->inheritedBy   = new BaseClassList;
00326     m_impl->inheritedBy->setAutoDelete(TRUE);
00327   }
00328   m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t));
00329 }
00330 
00331 void ClassDef::addMembersToMemberGroup()
00332 {
00333   QListIterator<MemberList> mli(m_impl->memberLists);
00334   MemberList *ml;
00335   for (mli.toFirst();(ml=mli.current());++mli)
00336   {
00337     if ((ml->listType()&MemberList::detailedLists)==0)
00338     {
00339       ::addMembersToMemberGroup(ml,&m_impl->memberGroupSDict,this);
00340     }
00341   }
00342 
00343   // add members inside sections to their groups
00344   if (m_impl->memberGroupSDict)
00345   {
00346     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
00347     MemberGroup *mg;
00348     for (;(mg=mgli.current());++mgli)
00349     {
00350       if (mg->allMembersInSameSection() && m_impl->subGrouping) 
00351       {
00352         //printf("addToDeclarationSection(%s)\n",mg->header().data());
00353         mg->addToDeclarationSection();
00354       }
00355     }
00356   }
00357 }
00358 
00359 // adds new member definition to the class
00360 void ClassDef::internalInsertMember(MemberDef *md,
00361                                     Protection prot,
00362                                     bool addToAllList
00363                                    )
00364 {
00365   //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden());
00366   if (md->isHidden()) return;
00367 
00368   if (!isReference())
00369   {
00370     static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE");
00371 
00372     /********************************************/
00373     /* insert member in the declaration section */
00374     /********************************************/
00375     if (md->isRelated() && (extractPrivate || prot!=Private))
00376     {
00377       addMemberToList(MemberList::related,md);
00378     }
00379     else if (md->isFriend())
00380     {
00381       addMemberToList(MemberList::friends,md);
00382     }
00383     else
00384     {
00385       switch (md->memberType())
00386       {
00387         case MemberDef::Signal: // Qt specific
00388           addMemberToList(MemberList::signals,md);
00389           break;
00390         case MemberDef::DCOP:   // KDE2 specific
00391           addMemberToList(MemberList::dcopMethods,md);
00392           break;
00393         case MemberDef::Property:
00394           addMemberToList(MemberList::properties,md);
00395           break;
00396         case MemberDef::Event:
00397           addMemberToList(MemberList::events,md);
00398           break;
00399         case MemberDef::Slot:   // Qt specific
00400           switch (prot)
00401           {
00402             case Protected: 
00403             case Package: // slots in packages are not possible!
00404               addMemberToList(MemberList::proSlots,md);
00405               break;
00406             case Public:    
00407               addMemberToList(MemberList::pubSlots,md);
00408               break;
00409             case Private:   
00410               addMemberToList(MemberList::priSlots,md);
00411               break;
00412           }
00413           break;
00414         default: // any of the other members
00415           if (md->isStatic())
00416           {
00417             if (md->isVariable())
00418             {
00419               switch (prot)
00420               {
00421                 case Protected: 
00422                   addMemberToList(MemberList::proStaticAttribs,md);
00423                   break;
00424                 case Package: 
00425                   addMemberToList(MemberList::pacStaticAttribs,md);
00426                   break;
00427                 case Public:    
00428                   addMemberToList(MemberList::pubStaticAttribs,md);
00429                   break;
00430                 case Private:   
00431                   addMemberToList(MemberList::priStaticAttribs,md);
00432                   break;
00433               }
00434             }
00435             else // function
00436             {
00437               switch (prot)
00438               {
00439                 case Protected: 
00440                   addMemberToList(MemberList::proStaticMethods,md);
00441                   break;
00442                 case Package: 
00443                   addMemberToList(MemberList::pacStaticMethods,md);
00444                   break;
00445                 case Public:    
00446                   addMemberToList(MemberList::pubStaticMethods,md);
00447                   break;
00448                 case Private:   
00449                   addMemberToList(MemberList::priStaticMethods,md);
00450                   break;
00451               }
00452             }
00453           }
00454           else // not static
00455           {
00456             if (md->isVariable())
00457             {
00458               switch (prot)
00459               {
00460                 case Protected: 
00461                   addMemberToList(MemberList::proAttribs,md);
00462                   break;
00463                 case Package:
00464                   addMemberToList(MemberList::pacAttribs,md);
00465                   break;
00466                 case Public:    
00467                   addMemberToList(MemberList::pubAttribs,md);
00468                   break;
00469                 case Private:   
00470                   addMemberToList(MemberList::priAttribs,md);
00471                   break;
00472               }
00473             }
00474             else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue())
00475             {
00476               switch (prot)
00477               {
00478                 case Protected: 
00479                   addMemberToList(MemberList::proTypes,md);
00480                   break;
00481                 case Package: 
00482                   addMemberToList(MemberList::pacTypes,md);
00483                   break;
00484                 case Public:    
00485                   addMemberToList(MemberList::pubTypes,md);
00486                   break;
00487                 case Private:   
00488                   addMemberToList(MemberList::priTypes,md);
00489                   break;
00490               }
00491             }
00492             else // member function
00493             {
00494               switch (prot)
00495               {
00496                 case Protected: 
00497                   addMemberToList(MemberList::proMethods,md);
00498                   break;
00499                 case Package: 
00500                   addMemberToList(MemberList::pacMethods,md);
00501                   break;
00502                 case Public:    
00503                   addMemberToList(MemberList::pubMethods,md);
00504                   break;
00505                 case Private:   
00506                   addMemberToList(MemberList::priMethods,md);
00507                   break;
00508               }
00509             }
00510           }
00511           break; 
00512       }
00513     }
00514 
00515     /*******************************************************/
00516     /* insert member in the detailed documentation section */
00517     /*******************************************************/
00518     if ((md->isRelated() && (extractPrivate || prot!=Private)) || md->isFriend())
00519     {
00520       addMemberToList(MemberList::relatedMembers,md);
00521     }
00522     else
00523     {
00524       switch (md->memberType())
00525       {
00526         case MemberDef::Property:
00527           addMemberToList(MemberList::propertyMembers,md);
00528           break;
00529         case MemberDef::Event:
00530           addMemberToList(MemberList::eventMembers,md);
00531           break;
00532         case MemberDef::Signal: // fall through
00533         case MemberDef::DCOP:
00534           addMemberToList(MemberList::functionMembers,md);
00535           break;
00536         case MemberDef::Slot:
00537           switch (prot)
00538           {
00539             case Protected: 
00540             case Package: 
00541             case Public:    
00542               addMemberToList(MemberList::functionMembers,md);
00543               break;
00544             case Private:   
00545               if (extractPrivate)
00546               {
00547                 addMemberToList(MemberList::functionMembers,md);
00548               }
00549               break;
00550           }
00551           break;
00552         default: // any of the other members
00553           if (prot!=Private || extractPrivate)
00554           {
00555             switch (md->memberType())
00556             {
00557               case MemberDef::Typedef:
00558                 addMemberToList(MemberList::typedefMembers,md);
00559                 break;
00560               case MemberDef::Enumeration:
00561                 addMemberToList(MemberList::enumMembers,md);
00562                 break;
00563               case MemberDef::EnumValue:
00564                 addMemberToList(MemberList::enumValMembers,md);
00565                 break;
00566               case MemberDef::Function:
00567                 if (md->isConstructor() || md->isDestructor())
00568                 {
00569                   MemberList *ml = createMemberList(MemberList::constructors);
00570                   ml->append(md);
00571                 }
00572                 else
00573                 {
00574                   addMemberToList(MemberList::functionMembers,md);
00575                 }
00576                 break;
00577               case MemberDef::Variable:
00578                 addMemberToList(MemberList::variableMembers,md);
00579                 break;
00580               default:
00581                 err("Unexpected member type %d found!\n",md->memberType());
00582             }
00583           }
00584           break; 
00585       }
00586     }
00587 
00588     /*************************************************/
00589     /* insert member in the appropriate member group */
00590     /*************************************************/
00591     // Note: this must be done AFTER inserting the member in the 
00592     // regular groups
00593     //addMemberToGroup(md,groupId);
00594     
00595   }
00596 
00597   if (md->virtualness()==Pure)
00598   {
00599     m_impl->isAbstract=TRUE;
00600   }
00601 
00602   //::addClassMemberNameToIndex(md);
00603   if (addToAllList && 
00604       !(Config_getBool("HIDE_FRIEND_COMPOUNDS") &&
00605         md->isFriend() &&
00606         (QCString(md->typeString())=="friend class" || 
00607          QCString(md->typeString())=="friend struct" ||
00608          QCString(md->typeString())=="friend union")))
00609   {
00610     //printf("=======> adding member %s to class %s\n",md->name().data(),name().data());
00611     MemberInfo *mi = new MemberInfo((MemberDef *)md,
00612                                      prot,md->virtualness(),FALSE);
00613     MemberNameInfo *mni=0;
00614     if (m_impl->allMemberNameInfoSDict==0)
00615     {
00616       m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
00617       m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
00618     }
00619     if ((mni=m_impl->allMemberNameInfoSDict->find(md->name())))
00620     {
00621       mni->append(mi);
00622     }
00623     else
00624     {
00625       mni = new MemberNameInfo(md->name());
00626       mni->append(mi);
00627       m_impl->allMemberNameInfoSDict->append(mni->memberName(),mni);
00628     }
00629   }
00630 }
00631 
00632 void ClassDef::insertMember(MemberDef *md)
00633 {
00634   internalInsertMember(md,md->protection(),TRUE);
00635 }
00636 
00637 // compute the anchors for all members
00638 void ClassDef::computeAnchors()
00639 {
00640   ClassDef *context = Config_getBool("INLINE_INHERITED_MEMB") ? this : 0;
00641   const char *letters = "abcdefghijklmnopqrstuvwxyz0123456789";
00642   QListIterator<MemberList> mli(m_impl->memberLists);
00643   MemberList *ml;
00644   int index = 0;
00645   for (mli.toFirst();(ml=mli.current());++mli)
00646   {
00647     if ((ml->listType()&MemberList::detailedLists)==0)
00648     {
00649       setAnchors(context,letters[index++],ml);
00650     }
00651   }
00652 
00653   if (m_impl->memberGroupSDict)
00654   {
00655     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
00656     MemberGroup *mg;
00657     for (;(mg=mgli.current());++mgli)
00658     {
00659       mg->setAnchors(context);
00660     }
00661   }
00662 }
00663 
00664 void ClassDef::distributeMemberGroupDocumentation()
00665 {
00666   if (m_impl->memberGroupSDict)
00667   {
00668     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
00669     MemberGroup *mg;
00670     for (;(mg=mgli.current());++mgli)
00671     {
00672       mg->distributeMemberGroupDocumentation();
00673     }
00674   }
00675 }
00676 
00677 void ClassDef::findSectionsInDocumentation()
00678 {
00679   docFindSections(documentation(),this,0,docFile());
00680   if (m_impl->memberGroupSDict)
00681   {
00682     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
00683     MemberGroup *mg;
00684     for (;(mg=mgli.current());++mgli)
00685     {
00686       mg->findSectionsInDocumentation();
00687     }
00688   }
00689   QListIterator<MemberList> mli(m_impl->memberLists);
00690   MemberList *ml;
00691   for (mli.toFirst();(ml=mli.current());++mli)
00692   {
00693     if ((ml->listType()&MemberList::detailedLists)==0)
00694     {
00695       ml->findSectionsInDocumentation();
00696     }
00697   }
00698 }
00699 
00700 
00701 // add a file name to the used files set
00702 void ClassDef::insertUsedFile(const char *f)
00703 {
00704   if (m_impl->files.find(f)==-1) m_impl->files.append(f);
00705   if (m_impl->templateInstances)
00706   {
00707     QDictIterator<ClassDef> qdi(*m_impl->templateInstances);
00708     ClassDef *cd;
00709     for (qdi.toFirst();(cd=qdi.current());++qdi)
00710     {
00711       cd->insertUsedFile(f);
00712     }
00713   }
00714 }
00715 
00716 static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd)
00717 {
00718   if (bcd->prot!=Public || bcd->virt!=Normal)
00719   {
00720     ol.startTypewriter();
00721     ol.docify(" [");
00722     QStrList sl;
00723     if (bcd->prot==Protected)    sl.append("protected");
00724     else if (bcd->prot==Private) sl.append("private");
00725     if (bcd->virt==Virtual)      sl.append("virtual");
00726     const char *s=sl.first();
00727     while (s)
00728     {
00729       ol.docify(s);
00730       s=sl.next();
00731       if (s) ol.docify(", ");
00732     }
00733     ol.docify("]");
00734     ol.endTypewriter();
00735   }
00736 }
00737 
00738 void ClassDef::setIncludeFile(FileDef *fd,
00739              const char *includeName,bool local, bool force)
00740 {
00741   //printf("ClassDef::setIncludeFile(%p,%s,%d,%d)\n",fd,includeName,local,force);
00742   if (!m_impl->incInfo) m_impl->incInfo=new IncludeInfo;
00743   if ((includeName && m_impl->incInfo->includeName.isEmpty()) ||
00744       (fd!=0 && m_impl->incInfo->fileDef==0)
00745      )
00746   {
00747     //printf("Setting file info\n");
00748     m_impl->incInfo->fileDef     = fd;
00749     m_impl->incInfo->includeName = includeName;
00750     m_impl->incInfo->local       = local;
00751   }
00752   if (force && includeName) m_impl->incInfo->includeName = includeName;
00753 }
00754 
00755 // TODO: fix this: a nested template class can have multiple outer templates
00756 //ArgumentList *ClassDef::outerTemplateArguments() const
00757 //{
00758 //  int ti;
00759 //  ClassDef *pcd=0;
00760 //  int pi=0;
00761 //  if (m_impl->tempArgs) return m_impl->tempArgs;
00762 //  // find the outer most class scope
00763 //  while ((ti=name().find("::",pi))!=-1 && 
00764 //      (pcd=getClass(name().left(ti)))==0
00765 //        ) pi=ti+2;
00766 //  if (pcd)
00767 //  {
00768 //    return pcd->templateArguments();
00769 //  }
00770 //  return 0;
00771 //}
00772 
00773 static void searchTemplateSpecs(/*in*/  Definition *d,
00774                                 /*out*/ QList<ArgumentList> &result,
00775                                 /*out*/ QCString &name)
00776 {
00777   if (d->definitionType()==Definition::TypeClass)
00778   {
00779     if (d->getOuterScope())
00780     {
00781       searchTemplateSpecs(d->getOuterScope(),result,name);
00782     }
00783     ClassDef *cd=(ClassDef *)d;
00784     if (!name.isEmpty()) name+="::";
00785     name+=d->localName();
00786     bool isSpecialization = d->localName().find('<')!=-1;
00787     if (cd->templateArguments()) 
00788     {
00789       result.append(cd->templateArguments());
00790       if (!isSpecialization)
00791       {
00792         name+=tempArgListToString(cd->templateArguments());
00793       }
00794     }
00795   }
00796   else
00797   {
00798     name+=d->qualifiedName();
00799   }
00800 }
00801 
00802 static void writeTemplateSpec(OutputList &ol,Definition *d,
00803             const QCString &type)
00804 {
00805   QList<ArgumentList> specs;
00806   QCString name;
00807   searchTemplateSpecs(d,specs,name);
00808   if (specs.count()>0) // class has template scope specifiers
00809   {
00810     ol.startSubsubsection(); 
00811     QListIterator<ArgumentList> spi(specs);
00812     ArgumentList *al;
00813     for (spi.toFirst();(al=spi.current());++spi)
00814     {
00815       ol.docify("template<");
00816       Argument *a=al->first();
00817       while (a)
00818       {
00819         ol.docify(a->type);
00820         if (!a->name.isEmpty())
00821         {
00822           ol.docify(" ");
00823           ol.docify(a->name);
00824         }
00825         if (a->defval.length()!=0)
00826         {
00827           ol.docify(" = ");
00828           ol.docify(a->defval);
00829         } 
00830         a=al->next();
00831         if (a) ol.docify(", ");
00832       }
00833       ol.docify(">");
00834       ol.pushGeneratorState();
00835       ol.disableAllBut(OutputGenerator::Html);
00836       ol.lineBreak();
00837       ol.popGeneratorState();
00838     }
00839     ol.docify(type.lower()+" "+name);
00840     ol.endSubsubsection();
00841     ol.writeString("\n");
00842   }
00843 }
00844 
00845 // write the detailed description for this class
00846 void ClassDef::writeDetailedDescription(OutputList &ol, const QCString &pageType, bool exampleFlag)
00847 {
00848   if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || 
00849       !documentation().isEmpty() || 
00850       (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) ||
00851       exampleFlag)
00852   {
00853     ol.writeRuler();
00854     ol.pushGeneratorState();
00855       ol.disable(OutputGenerator::Latex);
00856       ol.disable(OutputGenerator::RTF);
00857       ol.writeAnchor(0,"_details");
00858     ol.popGeneratorState();
00859     ol.startGroupHeader();
00860     ol.parseText(theTranslator->trDetailedDescription());
00861     ol.endGroupHeader();
00862     ol.startTextBlock();
00863     
00864     writeTemplateSpec(ol,this,pageType);
00865     
00866     // repeat brief description
00867     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))
00868     {
00869       ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
00870     }
00871     if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") &&
00872         !documentation().isEmpty())
00873     {
00874       ol.pushGeneratorState();
00875         ol.disable(OutputGenerator::Man);
00876         ol.disable(OutputGenerator::RTF);
00877         ol.newParagraph();
00878         ol.enableAll();
00879         ol.disableAllBut(OutputGenerator::Man);
00880         ol.writeString("\n\n");
00881       ol.popGeneratorState();
00882     }
00883     // write documentation
00884     if (!documentation().isEmpty())
00885     {
00886       //ol.newParagraph();
00887       ol.parseDoc(docFile(),docLine(),this,0,documentation(),TRUE,FALSE);
00888     }
00889     // write type constraints
00890     writeTypeConstraints(ol,this,m_impl->typeConstraints);
00891 
00892     // write examples
00893     if (exampleFlag && m_impl->exampleSDict)
00894     {
00895       ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
00896       ol.writeDescItem();
00897       ol.newParagraph();
00898       writeExample(ol,m_impl->exampleSDict);
00899       ol.endSimpleSect();
00900     }
00901     //ol.newParagraph();
00902     writeSourceDef(ol,name());
00903     ol.endTextBlock();
00904   }
00905   else
00906   {
00907     writeTemplateSpec(ol,this,pageType);
00908   }
00909 }
00910     
00911 void ClassDef::showUsedFiles(OutputList &ol)
00912 {
00913   bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
00914   if (Config_getBool("SHOW_USED_FILES"))
00915   {
00916     ol.writeRuler();
00917     if (fortranOpt)
00918     {
00919       ol.parseText(theTranslator->trGeneratedFromFilesFortran(
00920           m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType,
00921           m_impl->files.count()==1));
00922     }
00923     else
00924     {
00925       ol.parseText(theTranslator->trGeneratedFromFiles(
00926           m_impl->isObjC && m_impl->compType==Interface ? Class : m_impl->compType,
00927           m_impl->files.count()==1));  
00928     }
00929     
00930 
00931     bool first=TRUE;
00932     const char *file = m_impl->files.first();
00933     while (file)
00934     {
00935       bool ambig;
00936       FileDef *fd=findFileDef(Doxygen::inputNameDict,file,ambig);
00937       if (fd)
00938       {
00939         if (first)
00940         {
00941           first=FALSE;   
00942           ol.startItemList();
00943         }
00944 
00945         ol.writeListItem();
00946         QCString path=fd->getPath().copy();
00947         if (Config_getBool("FULL_PATH_NAMES"))
00948         {
00949           ol.docify(stripFromPath(path));
00950         }
00951 
00952         QCString fname = fd->name();
00953         if (!fd->getVersion().isEmpty()) // append version if available
00954         {
00955           fname += " (" + fd->getVersion() + ")";
00956         }
00957 
00958         // for HTML 
00959         ol.pushGeneratorState();
00960         ol.disableAllBut(OutputGenerator::Html);
00961         if (fd->generateSourceFile())
00962         {
00963           ol.writeObjectLink(0,fd->getSourceFileBase(),0,fname);
00964         }
00965         else if (fd->isLinkable())
00966         {
00967           ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
00968               fname);
00969         }
00970         else
00971         {
00972           ol.docify(fname);
00973         }
00974         ol.popGeneratorState();
00975 
00976         // for other output formats
00977         ol.pushGeneratorState();
00978         ol.disable(OutputGenerator::Html);
00979         if (fd->isLinkable())
00980         {
00981           ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,
00982               fname);
00983         }
00984         else
00985         {
00986           ol.docify(fname);
00987         }
00988 
00989         ol.popGeneratorState();
00990 
00991         
00992       }
00993       file=m_impl->files.next();
00994     }
00995     if (!first) ol.endItemList();
00996   }
00997 }
00998 
00999 
01000 void ClassDef::writeClassDiagrams(OutputList &ol)
01001 {
01002   // count direct inheritance relations
01003   int count=0;
01004   BaseClassDef *ibcd;
01005   if (m_impl->inheritedBy)
01006   {
01007     ibcd=m_impl->inheritedBy->first();
01008     while (ibcd)
01009     {
01010       ClassDef *icd=ibcd->classDef;
01011       if ( icd->isVisibleInHierarchy()) count++;
01012       ibcd=m_impl->inheritedBy->next();
01013     }
01014   }
01015   if (m_impl->inherits)
01016   {
01017     ibcd=m_impl->inherits->first();
01018     while (ibcd)
01019     {
01020       ClassDef *icd=ibcd->classDef;
01021       if ( icd->isVisibleInHierarchy()) count++;
01022       ibcd=m_impl->inherits->next();
01023     }
01024   }
01025 
01026   
01027   bool renderDiagram = FALSE;
01028   if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH"))
01029     // write class diagram using dot
01030   {
01031     DotClassGraph inheritanceGraph(this,DotNode::Inheritance);
01032     if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig())
01033     {
01034       ol.pushGeneratorState();
01035       ol.disable(OutputGenerator::Man);
01036       ol.startDotGraph();
01037       ol.parseText(theTranslator->trClassDiagram(displayName()));
01038       ol.endDotGraph(inheritanceGraph);
01039       ol.popGeneratorState();
01040       renderDiagram = TRUE;
01041     }
01042   }
01043   else if (Config_getBool("CLASS_DIAGRAMS") && count>0) 
01044     // write class diagram using build-in generator
01045   {
01046     ClassDiagram diagram(this); // create a diagram of this class.
01047     ol.startClassDiagram();
01048     ol.disable(OutputGenerator::Man);
01049     ol.parseText(theTranslator->trClassDiagram(displayName()));
01050     ol.enable(OutputGenerator::Man);
01051     ol.endClassDiagram(diagram,getOutputFileBase(),displayName());
01052     renderDiagram = TRUE;
01053   } 
01054 
01055   if (renderDiagram) // if we already show the inheritance relations graphically,
01056                      // then hide the text version
01057   {
01058     ol.disableAllBut(OutputGenerator::Man);
01059   }
01060 
01061   if (m_impl->inherits && (count=m_impl->inherits->count())>0)
01062   {
01063     //parseText(ol,theTranslator->trInherits()+" ");
01064 
01065     QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count());
01066     QRegExp marker("@[0-9]+");
01067     int index=0,newIndex,matchLen;
01068     // now replace all markers in inheritLine with links to the classes
01069     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
01070     {
01071       ol.parseText(inheritLine.mid(index,newIndex-index));
01072       bool ok;
01073       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
01074       BaseClassDef *bcd=m_impl->inherits->at(entryIndex);
01075       if (ok && bcd)
01076       {
01077         ClassDef *cd=bcd->classDef;
01078         if (cd->isLinkable())
01079         {
01080           if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
01081           {
01082             Doxygen::tagFile << "    <base";
01083             if (bcd->prot==Protected)
01084             {
01085               Doxygen::tagFile << " protection=\"protected\"";
01086             }
01087             else if (bcd->prot==Private)
01088             {
01089               Doxygen::tagFile << " protection=\"private\"";
01090             }
01091             if (bcd->virt==Virtual)
01092             {
01093               Doxygen::tagFile << " virtualness=\"virtual\"";
01094             }
01095             Doxygen::tagFile << ">" << convertToXML(cd->name()) 
01096                              << "</base>" << endl;
01097           }
01098           ol.writeObjectLink(cd->getReference(),
01099                              cd->getOutputFileBase(),
01100                              0,
01101                              cd->displayName()+bcd->templSpecifiers);
01102         }
01103         else
01104         {
01105           ol.docify(cd->displayName());
01106         }
01107       }
01108       else
01109       {
01110         err("Error: invalid marker %d in inherits list!\n",entryIndex);
01111       }
01112       index=newIndex+matchLen;
01113     } 
01114     ol.parseText(inheritLine.right(inheritLine.length()-index));
01115     ol.newParagraph();
01116   }
01117 
01118   // write subclasses
01119   if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0)
01120   {
01121     QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count());
01122     QRegExp marker("@[0-9]+");
01123     int index=0,newIndex,matchLen;
01124     // now replace all markers in inheritLine with links to the classes
01125     while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1)
01126     {
01127       ol.parseText(inheritLine.mid(index,newIndex-index));
01128       bool ok;
01129       uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
01130       BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex);
01131       if (ok && bcd)
01132       {
01133         ClassDef *cd=bcd->classDef;
01134         if (cd->isLinkable())
01135         {
01136           ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName());
01137         }
01138         else
01139         {
01140           ol.docify(cd->displayName());
01141         }
01142         writeInheritanceSpecifier(ol,bcd);
01143       }
01144       index=newIndex+matchLen;
01145     } 
01146     ol.parseText(inheritLine.right(inheritLine.length()-index));
01147     ol.newParagraph();
01148   }
01149 
01150   if (renderDiagram) 
01151   {
01152     ol.enableAll();
01153   }
01154 
01155   if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH"))
01156   {
01157     DotClassGraph usageImplGraph(this,DotNode::Collaboration);
01158     if (!usageImplGraph.isTrivial())
01159     {
01160       ol.pushGeneratorState();
01161       ol.disable(OutputGenerator::Man);
01162       ol.startDotGraph();
01163       ol.parseText(theTranslator->trCollaborationDiagram(displayName()));
01164       ol.endDotGraph(usageImplGraph);
01165       ol.popGeneratorState();
01166     }
01167   }
01168 
01169 }
01170 
01171 // write all documentation for this class
01172 void ClassDef::writeDocumentation(OutputList &ol)
01173 {
01174   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
01175   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
01176   QCString pageType = " ";
01177   QCString pageTitle = " ";
01178     
01179   pageType += compoundTypeString();
01180   toupper(pageType.at(1));
01181   if (fortranOpt)
01182   {
01183     pageTitle = theTranslator->trCompoundReferenceFortran(displayName(),
01184               m_impl->compType,
01185               m_impl->tempArgs != 0);  
01186   }
01187   else if (vhdlOpt)
01188   {
01189     // TODO: translate
01190     pageTitle = VhdlDocGen::getClassTitle(this)+" Reference";
01191   }
01192   else
01193   {
01194     pageTitle = theTranslator->trCompoundReference(displayName(),
01195               m_impl->compType == Interface && m_impl->isObjC ? Class : m_impl->compType,
01196               m_impl->tempArgs != 0);
01197   }
01198   
01199   startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_ClassVisible,TRUE);  
01200   if (getOuterScope()!=Doxygen::globalScope)
01201   {
01202     writeNavigationPath(ol);
01203   }
01204   ol.endQuickIndices();
01205   ol.startContents();
01206   startTitle(ol,getOutputFileBase());
01207   ol.parseText(pageTitle);
01208   addGroupListToTitle(ol,this);
01209   endTitle(ol,getOutputFileBase(),name());
01210 
01211   {
01212     ol.pushGeneratorState();
01213     ol.disableAllBut(OutputGenerator::Html);
01214     ol.writeString("<!-- doxytag: class=\"");
01215     ol.docify(name());
01216     ol.writeString("\" -->");
01217     if (m_impl->inherits && m_impl->inherits->count()>0)
01218     {
01219       BaseClassListIterator bli(*m_impl->inherits);
01220       ol.writeString("<!-- doxytag: inherits=\"");
01221       BaseClassDef *bcd=0;
01222       bool first=TRUE;
01223       for (bli.toFirst();(bcd=bli.current());++bli)
01224       {
01225         if (!first) ol.writeString(",");
01226         ol.docify(bcd->classDef->name());
01227         first=FALSE;
01228       }
01229       ol.writeString("\" -->");
01230     }
01231     ol.popGeneratorState();
01232   }
01233 
01234 
01235   if (Config_getBool("SEARCHENGINE"))
01236   {
01237     Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase());
01238     Doxygen::searchIndex->addWord(localName(),TRUE);
01239   }
01240 
01241   ol.startTextBlock();
01242   
01243   //printf("Class %s brief=`%s' doc=`%s'\n",name().data(),briefDescription().data(),documentation().data());
01244   
01245   bool exampleFlag=hasExamples();
01246   // write brief description
01247   if (!briefDescription().isEmpty())
01248   {
01249     if (!Config_getBool("DETAILS_AT_TOP")) 
01250     {
01251       ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE);
01252       ol.pushGeneratorState();
01253       ol.disable(OutputGenerator::RTF);
01254       ol.writeString(" \n");
01255       ol.enable(OutputGenerator::RTF);
01256       ol.disableAllBut(OutputGenerator::Html);
01257       ol.startTextLink(0,"_details");
01258     
01259       if (Config_getBool("REPEAT_BRIEF") || 
01260           !documentation().isEmpty() || 
01261           exampleFlag
01262          )
01263       {
01264         ol.parseText(theTranslator->trMore());
01265       }
01266       ol.endTextLink();
01267       ol.popGeneratorState();
01268 
01269       ol.pushGeneratorState();
01270       ol.disable(OutputGenerator::RTF);
01271       ol.newParagraph();
01272       ol.popGeneratorState();
01273     }
01274   }
01275   ol.writeSynopsis();
01276   
01277   if (m_impl->incInfo && Config_getBool("SHOW_INCLUDE_FILES"))
01278   {
01279     QCString nm=m_impl->incInfo->includeName.isEmpty() ? 
01280       (m_impl->incInfo->fileDef ?
01281        m_impl->incInfo->fileDef->docName().data() : "" 
01282       ) :
01283       m_impl->incInfo->includeName.data();
01284     if (!nm.isEmpty())
01285     {
01286       ol.startTypewriter();
01287       bool isIDLorJava = nm.right(4)==".idl" || 
01288                          nm.right(5)==".pidl" || 
01289                          nm.right(5)==".java";
01290       if (isIDLorJava)
01291       {
01292         ol.docify("import ");
01293       }
01294       else if (isObjectiveC())
01295       {
01296         ol.docify("#import ");
01297       }
01298       else
01299       {
01300         ol.docify("#include ");
01301       }
01302       if (m_impl->incInfo->local || isIDLorJava)
01303         ol.docify("\"");
01304       else
01305         ol.docify("<");
01306       ol.pushGeneratorState();
01307       ol.disable(OutputGenerator::Html);
01308       ol.docify(nm);
01309       ol.disableAllBut(OutputGenerator::Html);
01310       ol.enable(OutputGenerator::Html);
01311       if (m_impl->incInfo->fileDef)
01312       {
01313         ol.writeObjectLink(0,m_impl->incInfo->fileDef->includeName(),0,nm);
01314       }
01315       else
01316       {
01317         ol.docify(nm);
01318       }
01319       ol.popGeneratorState();
01320       if (m_impl->incInfo->local || isIDLorJava)
01321         ol.docify("\"");
01322       else
01323         ol.docify(">");
01324       if (isIDLorJava) 
01325         ol.docify(";");
01326       ol.endTypewriter();
01327       ol.newParagraph();
01328     }
01329   }
01330 
01331 
01332   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
01333   {
01334     Doxygen::tagFile << "  <compound kind=\"" << compoundTypeString();
01335     Doxygen::tagFile << "\"";
01336     if (isObjectiveC()) { Doxygen::tagFile << " objc=\"yes\""; }
01337     Doxygen::tagFile << ">" << endl;
01338     Doxygen::tagFile << "    <name>" << convertToXML(name()) << "</name>" << endl;
01339     Doxygen::tagFile << "    <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
01340     if (m_impl->tempArgs)
01341     {
01342       ArgumentListIterator ali(*m_impl->tempArgs);
01343       Argument *a;
01344       for (;(a=ali.current());++ali)
01345       {
01346         Doxygen::tagFile << "    <templarg>" << convertToXML(a->name) << "</templarg>" << endl;
01347       }
01348     }
01349   }
01350 
01351   writeClassDiagrams(ol); 
01352 
01353   // write link to list of all members (HTML only)
01354   if (m_impl->allMemberNameInfoSDict &&
01355       !Config_getBool("OPTIMIZE_OUTPUT_FOR_C")
01356      )
01357   {
01358     ol.pushGeneratorState();
01359     ol.disableAllBut(OutputGenerator::Html);
01360     ol.newParagraph();
01361     ol.startTextLink(getMemberListFileName(),0);
01362     ol.parseText(theTranslator->trListOfAllMembers());
01363     ol.endTextLink();
01364     ol.enableAll();
01365     ol.popGeneratorState();
01366   }
01367 
01368   ol.endTextBlock();
01369   
01370   // write detailed description if the user wants it near the top
01371   if (Config_getBool("DETAILS_AT_TOP")) 
01372   {
01373     writeDetailedDescription(ol,pageType,exampleFlag);
01374   }
01375 
01379 
01380   // write member groups
01381   ol.startMemberSections();
01382 
01383   // write user defined member groups
01384   if (m_impl->memberGroupSDict)
01385   {
01386     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
01387     MemberGroup *mg;
01388     for (;(mg=mgli.current());++mgli)
01389     {
01390       if (!mg->allMembersInSameSection() || !m_impl->subGrouping) // group is in its own section
01391       {
01392         mg->writeDeclarations(ol,this,0,0,0);
01393       }
01394       else // add this group to the corresponding member section
01395       {
01396         //printf("addToDeclarationSection(%s)\n",mg->header().data());
01397         //mg->addToDeclarationSection();
01398       }
01399     }
01400   }
01401 
01402   // public types
01403   writeMemberDeclarations(ol,MemberList::pubTypes,theTranslator->trPublicTypes()); 
01404 
01405   // public methods
01406   writeMemberDeclarations(ol,MemberList::pubSlots,theTranslator->trPublicSlots()); 
01407   writeMemberDeclarations(ol,MemberList::signals,theTranslator->trSignals()); 
01408   writeMemberDeclarations(ol,MemberList::dcopMethods,theTranslator->trDCOPMethods()); 
01409   writeMemberDeclarations(ol,MemberList::pubMethods,theTranslator->trPublicMembers()); 
01410   writeMemberDeclarations(ol,MemberList::pubStaticMethods,theTranslator->trStaticPublicMembers()); 
01411 
01412   // public attribs
01413   writeMemberDeclarations(ol,MemberList::pubAttribs,theTranslator->trPublicAttribs()); 
01414   writeMemberDeclarations(ol,MemberList::pubStaticAttribs,theTranslator->trStaticPublicAttribs()); 
01415   
01416   // protected types
01417   writeMemberDeclarations(ol,MemberList::proTypes,theTranslator->trProtectedTypes()); 
01418 
01419   // protected methods
01420   writeMemberDeclarations(ol,MemberList::proSlots,theTranslator->trProtectedSlots()); 
01421   writeMemberDeclarations(ol,MemberList::proMethods,theTranslator->trProtectedMembers()); 
01422   writeMemberDeclarations(ol,MemberList::proStaticMethods,theTranslator->trStaticProtectedMembers());
01423 
01424   // protected attribs
01425   writeMemberDeclarations(ol,MemberList::proAttribs,theTranslator->trProtectedAttribs()); 
01426   writeMemberDeclarations(ol,MemberList::proStaticAttribs,theTranslator->trStaticProtectedAttribs()); 
01427 
01428   // package types
01429   writeMemberDeclarations(ol,MemberList::pacTypes,theTranslator->trPackageTypes()); 
01430 
01431   // package methods
01432   writeMemberDeclarations(ol,MemberList::pacMethods,theTranslator->trPackageMembers()); 
01433   writeMemberDeclarations(ol,MemberList::pacStaticMethods,theTranslator->trStaticPackageMembers()); 
01434 
01435   // package attribs
01436   writeMemberDeclarations(ol,MemberList::pacAttribs,theTranslator->trPackageAttribs()); 
01437   writeMemberDeclarations(ol,MemberList::pacStaticAttribs,theTranslator->trStaticPackageAttribs()); 
01438 
01439   // package
01440   writeMemberDeclarations(ol,MemberList::properties,theTranslator->trProperties()); 
01441 
01442   // events
01443   writeMemberDeclarations(ol,MemberList::events,theTranslator->trEvents()); 
01444 
01445   if (Config_getBool("EXTRACT_PRIVATE"))
01446   {
01447     // private types
01448     writeMemberDeclarations(ol,MemberList::priTypes,theTranslator->trPrivateTypes()); 
01449 
01450     // private members
01451     writeMemberDeclarations(ol,MemberList::priSlots,theTranslator->trPrivateSlots()); 
01452     writeMemberDeclarations(ol,MemberList::priMethods,theTranslator->trPrivateMembers()); 
01453     writeMemberDeclarations(ol,MemberList::priStaticMethods,theTranslator->trStaticPrivateMembers()); 
01454 
01455     // private attribs
01456     writeMemberDeclarations(ol,MemberList::priAttribs,theTranslator->trPrivateAttribs()); 
01457     writeMemberDeclarations(ol,MemberList::priStaticAttribs,theTranslator->trStaticPrivateAttribs()); 
01458   }
01459 
01460   // friends
01461   writeMemberDeclarations(ol,MemberList::friends,theTranslator->trFriends());
01462 
01463   // related functions
01464   writeMemberDeclarations(ol,MemberList::related,theTranslator->trRelatedFunctions(),
01465                                               theTranslator->trRelatedSubscript()
01466                          ); 
01467   //if (related) related->writeDeclarations(ol,this,0,0,0,
01468   //                theTranslator->trRelatedFunctions(),
01469   //                theTranslator->trRelatedSubscript()
01470   //               ); 
01471 
01472   // nested classes
01473   if (m_impl->innerClasses) 
01474   {
01475     m_impl->innerClasses->writeDeclaration(ol,0,0,TRUE);
01476   }
01477 
01478   ol.endMemberSections();
01479     
01480   // write detailed description
01481   if (!Config_getBool("DETAILS_AT_TOP")) 
01482   {
01483     writeDetailedDescription(ol,pageType,exampleFlag);
01484   }
01485   
01486   writeMemberDocumentation(ol);
01487 
01489   ol.startTextBlock();
01490 
01491   // write the list of used files (not for man pages)
01492   ol.pushGeneratorState();
01493   ol.disable(OutputGenerator::Man);
01494 
01495   showUsedFiles(ol);
01496 
01497   // write Author section (Man only)
01498   ol.enable(OutputGenerator::Man);
01499   ol.disableAllBut(OutputGenerator::Man);
01500   ol.writeString("\n");
01501   ol.startGroupHeader();
01502   ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
01503   ol.endGroupHeader();
01504   ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME")));
01505   ol.popGeneratorState();
01506 
01507   ol.endTextBlock();
01509 
01510   if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 
01511   {
01512     writeDocAnchorsToTagFile();
01513     Doxygen::tagFile << "  </compound>" << endl;
01514   }
01515  
01516   endFile(ol);
01517 
01518   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
01519   {
01520     writeMemberPages(ol);
01521   }
01522 }
01523 
01524 void ClassDef::writeMemberDocumentation(OutputList &ol)
01525 {
01529   bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN");
01530     
01531   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
01532   {
01533     ol.disable(OutputGenerator::Html);
01534     Doxygen::suppressDocWarnings = TRUE;
01535   }
01536   
01537   writeMemberDocumentation(ol,MemberList::typedefMembers,theTranslator->trMemberTypedefDocumentation());
01538   writeMemberDocumentation(ol,MemberList::enumMembers,theTranslator->trMemberEnumerationDocumentation());
01539   writeMemberDocumentation(ol,MemberList::constructors,theTranslator->trConstructorDocumentation());
01540   if (fortranOpt)
01541   {
01542     writeMemberDocumentation(ol,MemberList::functionMembers,theTranslator->trMemberFunctionDocumentationFortran());
01543   }
01544   else
01545   {
01546     writeMemberDocumentation(ol,MemberList::functionMembers,theTranslator->trMemberFunctionDocumentation());
01547   }
01548   writeMemberDocumentation(ol,MemberList::relatedMembers,theTranslator->trRelatedFunctionDocumentation());
01549   writeMemberDocumentation(ol,MemberList::variableMembers,theTranslator->trMemberDataDocumentation());
01550   writeMemberDocumentation(ol,MemberList::propertyMembers,theTranslator->trPropertyDocumentation());
01551   writeMemberDocumentation(ol,MemberList::eventMembers,theTranslator->trEventDocumentation());
01552 
01553   if (Config_getBool("SEPARATE_MEMBER_PAGES"))
01554   {
01555     ol.enable(OutputGenerator::Html);
01556     Doxygen::suppressDocWarnings = FALSE;
01557   }
01558 }
01559 
01560 void ClassDef::writeMemberPages(OutputList &ol)
01561 {
01565 
01566   ol.pushGeneratorState();
01567   ol.disableAllBut(OutputGenerator::Html);
01568   
01569   QListIterator<MemberList> mli(m_impl->memberLists);
01570   MemberList *ml;
01571   for (mli.toFirst();(ml=mli.current());++mli)
01572   {
01573     if (ml->listType()&MemberList::detailedLists)
01574     {
01575       ml->writeDocumentationPage(ol,name(),this);
01576     }
01577   }
01578 
01579   ol.popGeneratorState();
01580 }
01581 
01582 void ClassDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
01583 {
01584   static bool createSubDirs=Config_getBool("CREATE_SUBDIRS");
01585 
01586   ol.writeString("      <div class=\"navtab\">\n");
01587   ol.writeString("        <table>\n");
01588 
01589   if (m_impl->allMemberNameInfoSDict)
01590   {
01591     MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
01592     MemberNameInfo *mni;
01593     for (;(mni=mnili.current());++mnili)
01594     {
01595       MemberNameInfoIterator mnii(*mni);
01596       MemberInfo *mi;
01597       for (mnii.toFirst();(mi=mnii.current());++mnii)
01598       {
01599         MemberDef *md=mi->memberDef;
01600         if (md->getClassDef()==this && md->isLinkable())
01601         {
01602           ol.writeString("          <tr><td class=\"navtab\">");
01603           if (md->isLinkableInProject())
01604           {
01605             if (md==currentMd) // selected item => highlight
01606             {
01607               ol.writeString("<a class=\"qindexHL\" ");
01608             }
01609             else
01610             {
01611               ol.writeString("<a class=\"qindex\" ");
01612             }
01613             ol.writeString("href=\"");
01614             if (createSubDirs) ol.writeString("../../");
01615             ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor());
01616             ol.writeString("\">");
01617             ol.writeString(md->name());
01618             ol.writeString("</a>");
01619           }
01620           ol.writeString("</td></tr>\n");
01621         }
01622       }
01623     }
01624   }
01625 
01626   ol.writeString("        </table>\n");
01627   ol.writeString("      </div>\n");
01628 }
01629 
01630 
01631 
01632 void ClassDef::writeDocumentationForInnerClasses(OutputList &ol)
01633 {
01634   // write inner classes after the parent, so the tag files contain
01635   // the definition in proper order!
01636   if (m_impl->innerClasses)
01637   {
01638     ClassSDict::Iterator cli(*m_impl->innerClasses);
01639     ClassDef *innerCd;
01640     for (cli.toFirst();(innerCd=cli.current());++cli)
01641     {
01642       if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 &&
01643           (innerCd->protection()!=Private || Config_getBool("EXTRACT_PRIVATE"))
01644          )
01645       {
01646         msg("Generating docs for nested compound %s...\n",innerCd->name().data());
01647         innerCd->writeDocumentation(ol);
01648         innerCd->writeMemberList(ol);
01649       }
01650       innerCd->writeDocumentationForInnerClasses(ol);
01651     }
01652   }
01653 }
01654 
01655 // write the list of all (inherited) members for this class
01656 void ClassDef::writeMemberList(OutputList &ol)
01657 {
01658   static bool cOpt    = Config_getBool("OPTIMIZE_OUTPUT_FOR_C");
01659   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
01660   if (m_impl->allMemberNameInfoSDict==0 || cOpt) return;
01661   // only for HTML
01662   ol.pushGeneratorState();
01663   ol.disableAllBut(OutputGenerator::Html);
01664 
01665   QCString memListFile = getMemberListFileName();
01666   startFile(ol,memListFile,memListFile,
01667             theTranslator->trMemberList(),HLI_ClassVisible);
01668   startTitle(ol,0);
01669   ol.parseText(displayName()+" "+theTranslator->trMemberList());
01670   endTitle(ol,0,0);
01671   ol.parseText(theTranslator->trThisIsTheListOfAllMembers());
01672   ol.writeObjectLink(getReference(),getOutputFileBase(),0,displayName());
01673   ol.parseText(theTranslator->trIncludingInheritedMembers());
01674   
01675   //ol.startItemList();
01676   ol.writeString("<p><table>\n");
01677   
01678   //MemberNameInfo *mni=m_impl->allMemberNameInfoList->first();
01679   MemberNameInfoSDict::Iterator mnii(*m_impl->allMemberNameInfoSDict); 
01680   MemberNameInfo *mni;
01681   for (mnii.toFirst();(mni=mnii.current());++mnii)
01682   {
01683     MemberInfo *mi=mni->first();
01684     while (mi)
01685     {
01686       MemberDef *md=mi->memberDef;
01687       ClassDef  *cd=md->getClassDef();
01688       Protection prot = mi->prot;
01689       Specifier virt=md->virtualness();
01690       
01691       //printf("%s: Member %s of class %s md->protection()=%d mi->prot=%d prot=%d inherited=%d\n",
01692       //    name().data(),md->name().data(),cd->name().data(),md->protection(),mi->prot,prot,mi->inherited);
01693 
01694 
01695       if (cd && !md->name().isEmpty() && md->name()[0]!='@')
01696       {
01697         bool memberWritten=FALSE;
01698         if (cd->isLinkable() && md->isLinkable()) 
01699           // create a link to the documentation
01700         {
01701           QCString name=mi->ambiguityResolutionScope+md->name();
01702           //ol.writeListItem();
01703           ol.writeString("  <tr class=\"memlist\"><td>");
01704           if (cd->isObjectiveC())
01705           {
01706             if (md->isObjCMethod())
01707             {
01708               if (md->isStatic())
01709                 ol.writeString("+&nbsp;</td><td>");
01710               else
01711                 ol.writeString("-&nbsp;</td><td>");
01712             }
01713             else
01714               ol.writeString("</td><td>");
01715           }
01716           if (md->isObjCMethod())
01717           {
01718             ol.writeObjectLink(md->getReference(),
01719                 md->getOutputFileBase(),
01720                 md->anchor(),md->name());
01721           }
01722           else
01723           {
01724             //Definition *bd = md->getGroupDef();
01725             //if (bd==0) bd=cd;
01726             ol.writeObjectLink(md->getReference(),
01727                 md->getOutputFileBase(),
01728                 md->anchor(),name);
01729 
01730             if ( md->isFunction() || md->isSignal() || md->isSlot() ||
01731                 (md->isFriend() && md->argsString())) 
01732               ol.docify(md->argsString());
01733             else if (md->isEnumerate())
01734               ol.parseText(" "+theTranslator->trEnumName());
01735             else if (md->isEnumValue())
01736               ol.parseText(" "+theTranslator->trEnumValue());
01737             else if (md->isTypedef())
01738               ol.docify(" typedef");
01739             else if (md->isFriend() && !strcmp(md->typeString(),"friend class"))
01740               ol.docify(" class");
01741             //ol.writeString("\n");
01742           }
01743           ol.writeString("</td>");
01744           memberWritten=TRUE;
01745         }
01746         else if (!Config_getBool("HIDE_UNDOC_MEMBERS") && 
01747                   (md->protection()!=Private || Config_getBool("EXTRACT_PRIVATE") || md->isFriend()) 
01748                 ) // no documentation, 
01749                   // generate link to the class instead.
01750         {
01751           //ol.writeListItem();
01752           ol.writeString("  <tr bgcolor=\"#f0f0f0\"><td>");
01753           if (cd->isObjectiveC())
01754           {
01755             if (md->isObjCMethod())
01756             {
01757               if (md->isStatic())
01758                 ol.writeString("+&nbsp;</td><td>");
01759               else
01760                 ol.writeString("-&nbsp;</td><td>");
01761             }
01762             else
01763               ol.writeString("</td><td>");
01764           }
01765           ol.startBold();
01766           ol.docify(md->name());
01767           ol.endBold();
01768           if (!md->isObjCMethod())
01769           {
01770             if ( md->isFunction() || md->isSignal() || md->isSlot() ) 
01771               ol.docify(md->argsString());
01772             else if (md->isEnumerate())
01773               ol.parseText(" "+theTranslator->trEnumName());
01774             else if (md->isEnumValue())
01775               ol.parseText(" "+theTranslator->trEnumValue());
01776             else if (md->isTypedef())
01777               ol.docify(" typedef");
01778           }
01779           ol.writeString(" (");
01780           ol.parseText(theTranslator->trDefinedIn()+" ");
01781           if (cd->isLinkable())
01782           {
01783             ol.writeObjectLink(
01784                 cd->getReference(),
01785                 cd->getOutputFileBase(),
01786                 0,
01787                 cd->displayName());
01788           }
01789           else
01790           {
01791             ol.startBold();
01792             ol.docify(cd->displayName());
01793             ol.endBold();
01794           }
01795           ol.writeString(")");
01796           ol.writeString("</td>");
01797           memberWritten=TRUE;
01798         }
01799         if (memberWritten)
01800         {
01801           ol.writeString("<td>");
01802           ol.writeObjectLink(cd->getReference(),
01803                              cd->getOutputFileBase(),
01804                              0,
01805                              cd->displayName());
01806           ol.writeString("</td>");
01807           ol.writeString("<td>");
01808         }
01809         if (
01810             (prot!=Public || (virt!=Normal && !m_impl->isObjC) || 
01811              md->isFriend() || md->isRelated() || md->isExplicit() ||
01812              md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) ||
01813              md->isSignal() || md->isSlot() ||
01814              md->isStatic() || vhdlOpt
01815             )
01816             && memberWritten)
01817         {
01818           ol.startTypewriter();
01819           ol.docify(" [");
01820           QStrList sl;
01821           if (vhdlOpt) sl.append(VhdlDocGen::trVhdlType(
01822                           md->getMemberSpecifiers())); //append vhdl type
01823           else if (md->isFriend()) sl.append("friend");
01824           else if (md->isRelated()) sl.append("related");
01825           else
01826           {
01827             if (Config_getBool("INLINE_INFO") && md->isInline())        
01828                                        sl.append("inline");
01829             if (md->isExplicit())      sl.append("explicit");
01830             if (md->isMutable())       sl.append("mutable");
01831             if (prot==Protected)       sl.append("protected");
01832             else if (prot==Private)    sl.append("private");
01833             else if (prot==Package)    sl.append("package");
01834             if (virt==Virtual && 
01835                 !m_impl->isObjC)             sl.append("virtual");
01836             else if (virt==Pure)       sl.append("pure virtual");
01837             if (md->isStatic())        sl.append("static");
01838             if (md->isSignal())        sl.append("signal");
01839             if (md->isSlot())          sl.append("slot");
01840           }
01841           const char *s=sl.first();
01842           while (s)
01843           {
01844             ol.docify(s);
01845             s=sl.next();
01846             if (s) ol.docify(", ");
01847           }
01848           ol.docify("]");
01849           ol.endTypewriter();
01850         }
01851         if (memberWritten)
01852         {
01853           ol.writeString("</td>");
01854           ol.writeString("</tr>\n");
01855         }
01856       }
01857       mi=mni->next();
01858     }
01859   }
01860   //ol.endItemList();
01861 
01862   ol.writeString("</table>");
01863   
01864   endFile(ol);
01865   ol.popGeneratorState();
01866 }
01867 
01868 
01869 // add a reference to an example
01870 bool ClassDef::addExample(const char *anchor,const char *nameStr,
01871     const char *file)
01872 {
01873   if (m_impl->exampleSDict==0)
01874   {
01875     m_impl->exampleSDict = new ExampleSDict;
01876     m_impl->exampleSDict->setAutoDelete(TRUE);
01877   }
01878   if (!m_impl->exampleSDict->find(nameStr))
01879   {
01880     Example *e=new Example;
01881     e->anchor=anchor;
01882     e->name=nameStr;
01883     e->file=file;
01884     m_impl->exampleSDict->inSort(nameStr,e);
01885     return TRUE;
01886   }
01887   return FALSE;
01888 }
01889 
01890 // returns TRUE if this class is used in an example
01891 bool ClassDef::hasExamples()
01892 {
01893   if (m_impl->exampleSDict==0) 
01894     return FALSE;
01895   else
01896     return m_impl->exampleSDict->count()>0;
01897 }
01898 
01899 
01900 void ClassDef::setTemplateArguments(ArgumentList *al)
01901 {
01902   if (al==0) return;
01903   if (!m_impl->tempArgs) delete m_impl->tempArgs; // delete old list if needed
01904   m_impl->tempArgs=new ArgumentList; 
01905   ArgumentListIterator ali(*al);
01906   Argument *a;
01907   for (;(a=ali.current());++ali)
01908   {
01909     m_impl->tempArgs->append(new Argument(*a));
01910   }
01911 }
01912 
01913 void ClassDef::setTypeConstraints(ArgumentList *al)
01914 {
01915   if (al==0) return;
01916   if (!m_impl->typeConstraints) delete m_impl->typeConstraints;
01917   m_impl->typeConstraints = new ArgumentList;
01918   ArgumentListIterator ali(*al);
01919   Argument *a;
01920   for (;(a=ali.current());++ali)
01921   {
01922     m_impl->typeConstraints->append(new Argument(*a));
01923   }
01924 }
01925 
01929 bool ClassDef::hasNonReferenceSuperClass()
01930 {
01931   bool found=!isReference() && isLinkableInProject() && !isHidden(); 
01932   if (found) 
01933   {
01934     return TRUE; // we're done if this class is not a reference
01935   }
01936   if (m_impl->inheritedBy)
01937   {
01938     BaseClassListIterator bcli(*m_impl->inheritedBy);
01939     for ( ; bcli.current() && !found ; ++bcli ) // for each super class
01940     {
01941       ClassDef *bcd=bcli.current()->classDef;
01942       // recurse into the super class branch
01943       found = found || bcd->hasNonReferenceSuperClass(); 
01944       if (!found)
01945       {
01946         // look for template instances that might have non-reference super classes
01947         QDict<ClassDef> *cil = bcd->getTemplateInstances();
01948         if (cil)
01949         {
01950           QDictIterator<ClassDef> tidi(*cil);
01951           for ( ; tidi.current() && !found ; ++tidi) // for each template instance
01952           {
01953             // recurse into the template instance branch
01954             found = found || tidi.current()->hasNonReferenceSuperClass();
01955           }
01956         }
01957       }
01958     }
01959   }
01960   return found;
01961 }
01962 
01966 void ClassDef::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup)
01967 {
01968   //ol.insertMemberAlign();
01969   //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup);
01970 
01971   //if (inGroup && md && md->getClassDef()==this) return;
01972 
01973   ol.docify(compoundTypeString());
01974   int ri=name().findRev("::");
01975   if (ri==-1) ri=name().length();
01976   QCString cn=name().right(name().length()-ri-2);
01977   if (!cn.isEmpty() && cn.at(0)!='@' && md)
01978   { 
01979     ol.docify(" ");
01980     if (isLinkable())
01981     {
01982       ol.writeObjectLink(0,0,md->anchor(),cn);
01983     }
01984     else
01985     {
01986       ol.startBold();
01987       ol.docify(cn);
01988       ol.endBold();
01989     }
01990   }
01991   ol.docify(" {");
01992   ol.endMemberItem(); 
01993 
01994   // write user defined member groups
01995   if (m_impl->memberGroupSDict)
01996   {
01997     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
01998     MemberGroup *mg;
01999     for (;(mg=mgli.current());++mgli)
02000     {
02001       mg->setInGroup(inGroup);
02002       mg->writePlainDeclarations(ol,this,0,0,0);
02003     }
02004   }
02005 
02006   writePlainMemberDeclaration(ol,MemberList::pubTypes,inGroup);
02007   writePlainMemberDeclaration(ol,MemberList::pubMethods,inGroup);
02008   writePlainMemberDeclaration(ol,MemberList::pubAttribs,inGroup);
02009   writePlainMemberDeclaration(ol,MemberList::pubSlots,inGroup);
02010   writePlainMemberDeclaration(ol,MemberList::signals,inGroup);
02011   writePlainMemberDeclaration(ol,MemberList::dcopMethods,inGroup);
02012   writePlainMemberDeclaration(ol,MemberList::properties,inGroup);
02013   writePlainMemberDeclaration(ol,MemberList::events,inGroup);
02014   writePlainMemberDeclaration(ol,MemberList::pubStaticMethods,inGroup);
02015   writePlainMemberDeclaration(ol,MemberList::pubStaticAttribs,inGroup);
02016   writePlainMemberDeclaration(ol,MemberList::proTypes,inGroup);
02017   writePlainMemberDeclaration(ol,MemberList::proMethods,inGroup);
02018   writePlainMemberDeclaration(ol,MemberList::proAttribs,inGroup);
02019   writePlainMemberDeclaration(ol,MemberList::proSlots,inGroup);
02020   writePlainMemberDeclaration(ol,MemberList::proStaticMethods,inGroup);
02021   writePlainMemberDeclaration(ol,MemberList::proStaticAttribs,inGroup);
02022   writePlainMemberDeclaration(ol,MemberList::pacTypes,inGroup);
02023   writePlainMemberDeclaration(ol,MemberList::pacMethods,inGroup);
02024   writePlainMemberDeclaration(ol,MemberList::pacAttribs,inGroup);
02025   writePlainMemberDeclaration(ol,MemberList::pacStaticMethods,inGroup);
02026   writePlainMemberDeclaration(ol,MemberList::pacStaticAttribs,inGroup);
02027   if (Config_getBool("EXTRACT_PRIVATE"))
02028   {
02029     writePlainMemberDeclaration(ol,MemberList::priTypes,inGroup);
02030     writePlainMemberDeclaration(ol,MemberList::priMethods,inGroup);
02031     writePlainMemberDeclaration(ol,MemberList::priAttribs,inGroup);
02032     writePlainMemberDeclaration(ol,MemberList::priSlots,inGroup);
02033     writePlainMemberDeclaration(ol,MemberList::priStaticMethods,inGroup);
02034     writePlainMemberDeclaration(ol,MemberList::priStaticAttribs,inGroup);
02035   }
02036   writePlainMemberDeclaration(ol,MemberList::friends,inGroup);
02037   writePlainMemberDeclaration(ol,MemberList::related,inGroup);
02038 }
02039 
02041 bool ClassDef::isLinkableInProject() const
02042 { 
02043   if (m_impl->templateMaster)
02044   {
02045     return m_impl->templateMaster->isLinkableInProject();
02046   }
02047   else
02048   {
02049     return !name().isEmpty() &&    /* no name */
02050       !isArtificial() && !isHidden() &&
02051       name().find('@')==-1 && /* anonymous compound */
02052       (m_impl->prot!=Private || Config_getBool("EXTRACT_PRIVATE")) && /* private */
02053       (!m_impl->isLocal || Config_getBool("EXTRACT_LOCAL_CLASSES")) && /* local */
02054       hasDocumentation() &&   /* documented */ 
02055       !isReference() &&         /* not an external reference */
02056       (!m_impl->isStatic || Config_getBool("EXTRACT_STATIC"));
02057   }
02058 }
02059 
02060 bool ClassDef::isLinkable() const
02061 {
02062   if (m_impl->templateMaster)
02063   {
02064     return m_impl->templateMaster->isLinkable();
02065   }
02066   else
02067   {
02068     return isLinkableInProject() || isReference();
02069   }
02070 }
02071 
02072 
02074 bool ClassDef::isVisibleInHierarchy() 
02075 { 
02076   static bool allExternals     = Config_getBool("ALLEXTERNALS");
02077   static bool extractPrivate   = Config_getBool("EXTRACT_PRIVATE");
02078   static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES");
02079   static bool extractStatic    = Config_getBool("EXTRACT_STATIC");
02080 
02081   return // show all classes or a subclass is visible
02082       (allExternals || hasNonReferenceSuperClass()) &&
02083       // and not an annonymous compound
02084       name().find('@')==-1 &&
02085       // not an artifically introduced class
02086       !isArtificial() &&
02087       // and not privately inherited
02088       (m_impl->prot!=Private || extractPrivate) &&
02089       // documented or shown anyway or documentation is external 
02090       (hasDocumentation() || 
02091        !hideUndocClasses || 
02092        (m_impl->templateMaster && m_impl->templateMaster->hasDocumentation()) || 
02093        isReference()
02094       ) &&
02095       // is not part of an unnamed namespace or shown anyway
02096       (!m_impl->isStatic || extractStatic);
02097 }
02098 
02099 bool ClassDef::hasDocumentation() const
02100 {
02101   return Definition::hasDocumentation();
02102 }
02103 
02104 //----------------------------------------------------------------------
02105 // recursive function:
02106 // returns TRUE iff class definition `bcd' represents an (in)direct base 
02107 // class of class definition `cd'.
02108 
02109 bool ClassDef::isBaseClass(ClassDef *bcd, bool followInstances,int level)
02110 {
02111   bool found=FALSE;
02112   //printf("isBaseClass(cd=%s) looking for %s\n",cd->name().data(),bcd->name().data());
02113   if (level>256)
02114   {
02115     err("Possible recursive class relation while inside %s and looking for %s\n",name().data(),bcd->name().data());
02116     abort();
02117     return FALSE;
02118   }
02119   if (baseClasses())
02120   {
02121     BaseClassListIterator bcli(*baseClasses());
02122     for ( ; bcli.current() && !found ; ++bcli)
02123     {
02124       ClassDef *ccd=bcli.current()->classDef;
02125       if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
02126       //printf("isBaseClass() baseclass %s\n",ccd->name().data());
02127       if (ccd==bcd) 
02128         found=TRUE;
02129       else 
02130         found=ccd->isBaseClass(bcd,followInstances,level+1);
02131     }
02132   }
02133   return found;
02134 }
02135 
02136 //----------------------------------------------------------------------------
02137 
02138 static bool isStandardFunc(MemberDef *md)
02139 {
02140   return md->name()=="operator=" || // assignment operator
02141          md->isConstructor() ||     // constructor
02142          md->isDestructor();        // destructor
02143 }
02144 
02151 void ClassDef::mergeMembers()
02152 {
02153   if (m_impl->membersMerged) return;
02154 
02155   static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
02156   static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
02157   QCString sep="::";
02158   if (optimizeOutputForJava || vhdlOpt) sep=".";
02159   int sepLen = sep.length();
02160 
02161   m_impl->membersMerged=TRUE;
02162   //printf("  mergeMembers for %s\n",name().data());
02163   bool inlineInheritedMembers = Config_getBool("INLINE_INHERITED_MEMB" );
02164   if (baseClasses())
02165   {
02166     //printf("  => has base classes!\n");
02167     BaseClassListIterator bcli(*baseClasses());
02168     BaseClassDef *bcd;
02169     for ( ; (bcd=bcli.current()) ; ++bcli )
02170     {
02171       ClassDef *bClass=bcd->classDef; 
02172 
02173       // merge the members in the base class of this inheritance branch first
02174       bClass->mergeMembers();
02175 
02176       MemberNameInfoSDict *srcMnd  = bClass->memberNameInfoSDict();
02177       MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
02178 
02179       if (srcMnd)
02180       {
02181         MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
02182         MemberNameInfo *srcMni;
02183         for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
02184         {
02185           //printf("    Base member name %s\n",srcMni->memberName());
02186           MemberNameInfo *dstMni;
02187           if (dstMnd!=0 && (dstMni=dstMnd->find(srcMni->memberName())))
02188             // a member with that name is already in the class.
02189             // the member may hide or reimplement the one in the sub class
02190             // or there may be another path to the base class that is already 
02191             // visited via another branch in the class hierarchy.
02192           {
02193             MemberNameInfoIterator srcMnii(*srcMni); 
02194             MemberInfo *srcMi;
02195             for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
02196             {
02197               MemberDef *srcMd = srcMi->memberDef;
02198               bool found=FALSE;
02199               bool ambigue=FALSE;
02200               bool hidden=FALSE;
02201               MemberNameInfoIterator dstMnii(*dstMni); 
02202               MemberInfo *dstMi;
02203               ClassDef *srcCd = srcMd->getClassDef();
02204               for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
02205               {
02206                 MemberDef *dstMd = dstMi->memberDef;
02207                 if (srcMd!=dstMd) // different members
02208                 {
02209                   ClassDef *dstCd = dstMd->getClassDef();
02210                   //printf("  Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data());
02211                   if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) 
02212                     // member is in the same or a base class
02213                   {
02214                     LockingPtr<ArgumentList> srcAl = srcMd->argumentList();
02215                     LockingPtr<ArgumentList> dstAl = dstMd->argumentList();
02216                     found=matchArguments2(
02217                         srcMd->getOuterScope(),srcMd->getFileDef(),srcAl.pointer(),
02218                         dstMd->getOuterScope(),dstMd->getFileDef(),dstAl.pointer(),
02219                         TRUE
02220                         );
02221                     //printf("  Yes, matching (%s<->%s): %d\n",
02222                     //    argListToString(srcMd->argumentList()).data(),
02223                     //    argListToString(dstMd->argumentList()).data(),
02224                     //    found);
02225                     hidden = hidden  || !found;
02226                   }
02227                   else // member is in a non base class => multiple inheritance
02228                     // using the same base class.
02229                   {
02230                     //printf("$$ Existing member %s %s add scope %s\n",
02231                     //    dstMi->ambiguityResolutionScope.data(),
02232                     //    dstMd->name().data(),
02233                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
02234 
02235                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
02236                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
02237                       dstMi->ambiguityResolutionScope.prepend(scope);
02238                     ambigue=TRUE;
02239                   }
02240                 }
02241                 else // same members
02242                 {
02243                   // do not add if base class is virtual or 
02244                   // if scope paths are equal or
02245                   // if base class is an interface (and thus implicitly virtual).
02246                   //printf("same member found srcMi->virt=%d dstMi->virt=%d\n",srcMi->virt,dstMi->virt);
02247                   if ((srcMi->virt!=Normal && dstMi->virt!=Normal) ||
02248                       bClass->name()+sep+srcMi->scopePath == dstMi->scopePath ||
02249                       dstMd->getClassDef()->compoundType()==Interface
02250                      ) 
02251                   {
02252                     found=TRUE;
02253                   }
02254                   else // member can be reached via multiple paths in the 
02255                     // inheritance tree
02256                   {
02257                     //printf("$$ Existing member %s %s add scope %s\n",
02258                     //    dstMi->ambiguityResolutionScope.data(),
02259                     //    dstMd->name().data(),
02260                     //    dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
02261 
02262                     QCString scope=dstMi->scopePath.left(dstMi->scopePath.find(sep)+sepLen);
02263                     if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
02264                     {
02265                       dstMi->ambiguityResolutionScope.prepend(scope);
02266                     }
02267                     ambigue=TRUE;
02268                   }
02269                 }
02270               }
02271               //printf("member %s::%s hidden %d ambigue %d srcMi->ambigClass=%p\n",
02272               //    srcCd->name().data(),srcMd->name().data(),hidden,ambigue,srcMi->ambigClass);
02273 
02274               // TODO: fix the case where a member is hidden by inheritance
02275               //       of a member with the same name but with another prototype,
02276               //       while there is more than one path to the member in the 
02277               //       base class due to multiple inheritance. In this case
02278               //       it seems that the member is not reachable by prefixing a 
02279               //       scope name either (according to my compiler). Currently, 
02280               //       this case is shown anyway.
02281               if (!found && srcMd->protection()!=Private)
02282               {
02283                 Protection prot=srcMd->protection();
02284                 if (bcd->prot==Protected && prot==Public)       prot=bcd->prot;
02285                 else if (bcd->prot==Private)                    prot=bcd->prot;
02286 
02287                 if (inlineInheritedMembers)
02288                 {
02289                   if (!isStandardFunc(srcMd))
02290                   {
02291                     //printf("    insertMember `%s'\n",srcMd->name().data());
02292                     internalInsertMember(srcMd,prot,FALSE);
02293                   }
02294                 }
02295 
02296                 Specifier virt=srcMi->virt;
02297                 if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
02298 
02299                 MemberInfo *newMi = new MemberInfo(srcMd,prot,virt,TRUE);
02300                 newMi->scopePath=bClass->name()+sep+srcMi->scopePath;
02301                 if (ambigue)
02302                 {
02303                   //printf("$$ New member %s %s add scope %s::\n",
02304                   //     srcMi->ambiguityResolutionScope.data(),
02305                   //     srcMd->name().data(),
02306                   //     bClass->name().data());
02307 
02308                   QCString scope=bClass->name()+sep;
02309                   if (scope!=srcMi->ambiguityResolutionScope.left(scope.length()))
02310                   {
02311                     newMi->ambiguityResolutionScope=
02312                       scope+srcMi->ambiguityResolutionScope.copy();
02313                   }
02314                 }
02315                 if (hidden)
02316                 {
02317                   if (srcMi->ambigClass==0)
02318                   {
02319                     newMi->ambigClass=bClass;
02320                     newMi->ambiguityResolutionScope=bClass->name()+sep;
02321                   }
02322                   else
02323                   {
02324                     newMi->ambigClass=srcMi->ambigClass;
02325                     newMi->ambiguityResolutionScope=srcMi->ambigClass->name()+sep;
02326                   }
02327                 }
02328                 dstMni->append(newMi);
02329               }
02330             }
02331           }
02332           else // base class has a member that is not in the sub class => copy
02333           {
02334             // create a deep copy of the list (only the MemberInfo's will be 
02335             // copied, not the actual MemberDef's)
02336             MemberNameInfo *newMni = 0;
02337             newMni = new MemberNameInfo(srcMni->memberName()); 
02338 
02339             // copy the member(s) from the base to the sub class
02340             MemberNameInfoIterator mnii(*srcMni);
02341             MemberInfo *mi;
02342             for (;(mi=mnii.current());++mnii)
02343             {
02344               Protection prot = mi->prot;
02345               if (bcd->prot==Protected)
02346               {
02347                 if (prot==Public) prot=Protected;
02348               }
02349               else if (bcd->prot==Private)
02350               {
02351                 prot=Private;
02352               }
02353               //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n",
02354               //    name().data(),mi->memberDef->name().data(),mi->prot,
02355               //    bcd->prot,prot);
02356 
02357               if (mi->prot!=Private)
02358               {
02359                 Specifier virt=mi->virt;
02360                 if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
02361 
02362                 if (inlineInheritedMembers)
02363                 {
02364                   if (!isStandardFunc(mi->memberDef))
02365                   {
02366                     //printf("    insertMember `%s'\n",mi->memberDef->name().data());
02367                     internalInsertMember(mi->memberDef,prot,FALSE);
02368                   }
02369                 }
02370                 //printf("Adding!\n");
02371                 MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,virt,TRUE);
02372                 newMi->scopePath=bClass->name()+sep+mi->scopePath;
02373                 newMi->ambigClass=mi->ambigClass;
02374                 newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
02375                 newMni->append(newMi);
02376               }
02377             }
02378 
02379             if (dstMnd==0)
02380             {
02381               m_impl->allMemberNameInfoSDict = new MemberNameInfoSDict(17);
02382               m_impl->allMemberNameInfoSDict->setAutoDelete(TRUE);
02383               dstMnd = m_impl->allMemberNameInfoSDict;
02384             }
02385             // add it to the dictionary
02386             dstMnd->append(newMni->memberName(),newMni);
02387           }
02388         }
02389       }
02390     }
02391   }
02392   //printf("  end mergeMembers\n");
02393 }
02394 
02395 //----------------------------------------------------------------------------
02396 
02399 void ClassDef::mergeCategory(ClassDef *category)
02400 {
02401   category->setCategoryOf(this);
02402     
02403   MemberNameInfoSDict *srcMnd  = category->memberNameInfoSDict();
02404   MemberNameInfoSDict *dstMnd  = m_impl->allMemberNameInfoSDict;
02405 
02406   if (srcMnd && dstMnd)
02407   {
02408     MemberNameInfoSDict::Iterator srcMnili(*srcMnd);
02409     MemberNameInfo *srcMni;
02410     for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
02411     {
02412       MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName());
02413       if (dstMni) // method is already defined in the class
02414       {
02415         // TODO: we should remove the other member and insert this one.
02416       }
02417       else // new method name
02418       {
02419         // create a deep copy of the list (only the MemberInfo's will be 
02420         // copied, not the actual MemberDef's)
02421         MemberNameInfo *newMni = 0;
02422         newMni = new MemberNameInfo(srcMni->memberName()); 
02423 
02424         // copy the member(s) from the category to this class
02425         MemberNameInfoIterator mnii(*srcMni);
02426         MemberInfo *mi;
02427         for (;(mi=mnii.current());++mnii)
02428         {
02429           //printf("Adding!\n");
02430           MemberInfo *newMi=new MemberInfo(mi->memberDef,mi->prot,mi->virt,mi->inherited);
02431           newMi->scopePath=mi->scopePath;
02432           newMi->ambigClass=mi->ambigClass;
02433           newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
02434           newMni->append(newMi);
02435         }
02436 
02437         // add it to the dictionary
02438         dstMnd->append(newMni->memberName(),newMni);
02439       }
02440     }
02441   }
02442 }
02443 
02444 //----------------------------------------------------------------------------
02445 
02446 void ClassDef::addUsedClass(ClassDef *cd,const char *accessName)
02447 {
02448   //printf("%s::addUsedClass(%s,%s)\n",name().data(),cd->name().data(),accessName);
02449   if (m_impl->usesImplClassDict==0) 
02450   {
02451     m_impl->usesImplClassDict = new UsesClassDict(17); 
02452     m_impl->usesImplClassDict->setAutoDelete(TRUE);
02453   }
02454   UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
02455   if (ucd==0)
02456   {
02457      ucd = new UsesClassDef(cd);
02458      m_impl->usesImplClassDict->insert(cd->name(),ucd);
02459      //printf("Adding used class %s to class %s\n",
02460      //    cd->name().data(),name().data());
02461   }
02462   ucd->addAccessor(accessName);
02463 }
02464 
02465 void ClassDef::addUsedByClass(ClassDef *cd,const char *accessName)
02466 {
02467   if (m_impl->usedByImplClassDict==0) 
02468   {
02469     m_impl->usedByImplClassDict = new UsesClassDict(17); 
02470     m_impl->usedByImplClassDict->setAutoDelete(TRUE);
02471   }
02472   UsesClassDef *ucd=m_impl->usedByImplClassDict->find(cd->name());
02473   if (ucd==0)
02474   {
02475      ucd = new UsesClassDef(cd);
02476      m_impl->usedByImplClassDict->insert(cd->name(),ucd);
02477      //printf("Adding used by class %s to class %s\n",
02478      //    cd->name().data(),name().data());
02479   }
02480   ucd->addAccessor(accessName);
02481 }
02482 
02483 
02484 #if 0
02485 
02490 void ClassDef::determineImplUsageRelation()
02491 {
02492   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
02493   MemberNameInfo *mni;
02494   for (;(mni=mnili.current());++mnili)
02495   {
02496     MemberNameInfoIterator mnii(*mni);
02497     MemberInfo *mi;
02498     for (mnii.toFirst();(mi=mnii.current());++mnii)
02499     {
02500       MemberDef *md=mi->memberDef;
02501       if (md->isVariable()) // for each member variable in this class
02502       {
02503         QCString type=removeRedundantWhiteSpace(md->typeString());
02504         //printf("in class %s found var type=`%s' name=`%s'\n",
02505         //            name().data(),type.data(),md->name().data());
02506         int pos=0;
02507         QCString usedClassName;
02508         QCString templSpec;
02509         bool found=FALSE;
02510         while (extractClassNameFromType(type,pos,usedClassName,templSpec)!=-1 && !found)
02511         {
02512           //printf("usedClassName=`%s' templSpec=%s\n",usedClassName.data(),templSpec.data());
02513           // check if usedClassName is a template argument of its class
02514           ClassDef *cd=md->getClassDef();
02515           if (cd && cd->templateArguments())
02516           {
02517             ArgumentListIterator ali(*cd->templateArguments());
02518             Argument *arg;
02519             int count=0;
02520             for (ali.toFirst();(arg=ali.current());++ali,++count)
02521             {
02522               if (arg->name==usedClassName) // type is a template argument
02523               {
02524                 found=TRUE;
02525                 if (m_impl->usesImplClassDict==0) m_impl->usesImplClassDict = new UsesClassDict(257); 
02526                 cd = new ClassDef(cd->getDefFileName(),cd->getDefLine(),
02527                     usedClassName,ClassDef::Class);
02528                 cd->setIsTemplateBaseClass(count);
02529                 UsesClassDef *ucd = new UsesClassDef(cd);
02530                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
02531                 ucd->templSpecifiers = templSpec;
02532                 ucd->addAccessor(md->name());
02533                 Doxygen::hiddenClasses.append(cd);
02534                 //printf("Adding used template argument %s to class %s\n",
02535                 //    cd->name().data(),name().data());
02536                 //printf("Adding accessor %s to class %s\n",
02537                 //    md->name().data(),ucd->classDef->name().data());
02538               }
02539             }
02540           }
02541 
02542           if (!found)
02543           {
02544             cd=0;
02545             if (getNamespaceDef()!=0)
02546             {
02547               cd=getResolvedClass(getNamespaceDef()->name()+"::"+usedClassName,0,&templSpec);
02548             }
02549             if (cd==0) cd=getResolvedClass(name()+"::"+usedClassName,0,&templSpec);
02550             if (cd==0) cd=getResolvedClass(usedClassName,0,&templSpec); // TODO: also try inbetween scopes!
02551             //printf("Search for class %s result=%p\n",usedClassName.data(),cd);
02552             if (cd) // class exists 
02553             {
02554               found=TRUE;
02555               if (m_impl->usesImplClassDict==0) 
02556               {
02557                 m_impl->usesImplClassDict = new UsesClassDict(257); 
02558                 m_impl->usesImplClassDict->setAutoDelete(TRUE);
02559               }
02560               UsesClassDef *ucd=m_impl->usesImplClassDict->find(cd->name());
02561               if (ucd==0 || ucd->templSpecifiers!=templSpec)
02562               {
02563                 ucd = new UsesClassDef(cd);
02564                 m_impl->usesImplClassDict->insert(cd->name(),ucd);
02565                 ucd->templSpecifiers = templSpec;
02566                 //printf("Adding used class %s to class %s\n",
02567                 //    cd->name().data(),name().data());
02568               }
02569               ucd->addAccessor(md->name());
02570               //printf("Adding accessor %s to class %s\n",
02571               //    md->name().data(),ucd->classDef->name().data());
02572             }
02573           }
02574         }
02575       }
02576     }
02577   }
02578 #ifdef DUMP
02579   if (m_impl->usesClassDict)
02580   {
02581     msg("Class %s uses the following classes:\n",name().data());
02582     UsesClassDictIterator ucdi(*m_impl->usesClassDict);
02583     UsesClassDef *ucd;
02584     for (;(ucd=ucdi.current());++ucdi)
02585     {
02586       msg("  %s via ",ucd->classDef->name().data());
02587       QDictIterator<void> dvi(*ucd->accessors); 
02588       const char *s;
02589       for (;(s=dvi.currentKey());++dvi)
02590       {
02591         msg("%s ",s);
02592       }
02593       msg("\n");
02594     }
02595   }
02596 #endif
02597 }
02598 
02599 //----------------------------------------------------------------------------
02600 
02601 // I have disabled this code because the graphs it renders quickly become
02602 // too large to be of practical use.
02603 
02604 void ClassDef::addUsedInterfaceClasses(MemberDef *md,const char *typeStr)
02605 {
02606   QCString type = typeStr;
02607   static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
02608   int p=0,i,l;
02609   while ((i=re.match(type,p,&l))!=-1) // for each class name in the type
02610   {
02611     ClassDef *cd=getClass(name()+"::"+type.mid(i,l));
02612     if (cd==0) cd=getClass(type.mid(i,l)); // TODO: also try inbetween scopes!
02613     if (cd && cd!=this && !isBaseClass(cd))
02614     {
02615       if (m_impl->usesIntfClassDict==0) 
02616       {
02617         m_impl->usesIntfClassDict = new UsesClassDict(257); 
02618       }
02619       UsesClassDef *ucd=m_impl->usesIntfClassDict->find(cd->name());
02620       if (ucd==0)
02621       {
02622         ucd = new UsesClassDef(cd);
02623         m_impl->usesIntfClassDict->insert(cd->name(),ucd);
02624         //printf("in class `%s' adding used intf class `%s'\n",
02625         //  name().data(),cd->name().data());
02626       }
02627       ucd->addAccessor(md->name());
02628       //printf("in class `%s' adding accessor `%s' to class `%s'\n",
02629       //    name().data(),md->name().data(),ucd->classDef->name().data());
02630     }
02631     p=i+l;
02632   }
02633 }
02634 
02635 void ClassDef::determineIntfUsageRelation()
02636 {
02637   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoList);
02638   MemberNameInfo *mni;
02639   for (;(mni=mnili.current());++mnili)
02640   {
02641     MemberNameInfoIterator mnii(*mni);
02642     MemberInfo *mi;
02643     for (mnii.toFirst();(mi=mnii.current());++mnii)
02644     {
02645       MemberDef *md=mi->memberDef;
02646       
02647       // compute the protection level for this member
02648       Protection protect=md->protection();
02649       if (mi->prot==Protected) // inherited protection
02650       {
02651         if (protect==Public) protect=Protected;
02652         else if (protect==Protected) protect=Private;
02653       }
02654       
02655       if (!md->name().isEmpty() && md->name()[0]!='@' && 
02656           (mi->prot!=Private && protect!=Private)
02657          )
02658       {
02659         // add classes found in the return type
02660         addUsedInterfaceClasses(md,md->typeString());
02661         ArgumentList *al = md->argumentList();
02662         if (al) // member has arguments
02663         {
02664           // add classes found in the types of the argument list
02665           ArgumentListIterator ali(*al);
02666           Argument *a;
02667           for (;(a=ali.current());++ali)
02668           {
02669             if (!a->type.isEmpty() && a->type.at(0)!='@')
02670             {
02671               addUsedInterfaceClasses(md,a->type);
02672             }
02673           }
02674         }
02675       }
02676     }
02677   }
02678 }
02679 #endif
02680 
02681 QCString ClassDef::compoundTypeString() const
02682 {
02683   if (m_impl->compType==Interface && m_impl->isObjC) return "class";
02684   if (Config_getBool("OPTIMIZE_FOR_FORTRAN"))
02685   {
02686     switch (m_impl->compType)
02687     {
02688       case Class:     return "module";
02689       case Struct:    return "type";
02690       case Union:     return "union";
02691       case Interface: return "interface";
02692       case Protocol:  return "protocol";
02693       case Category:  return "category";
02694       case Exception: return "exception";
02695       default:        return "unknown";
02696     } 
02697   }
02698   else
02699   {
02700     switch (m_impl->compType)
02701     {
02702       case Class:     return "class";
02703       case Struct:    return "struct";
02704       case Union:     return "union";
02705       case Interface: return "interface";
02706       case Protocol:  return "protocol";
02707       case Category:  return "category";
02708       case Exception: return "exception";
02709       default:        return "unknown";
02710     }
02711   }
02712 }
02713 
02714 QCString ClassDef::getOutputFileBase() const 
02715 { 
02716   if (m_impl->templateMaster)
02717   {
02718     return m_impl->templateMaster->getOutputFileBase();
02719   }
02720   else if (isReference())
02721   {
02722     return m_impl->fileName;
02723   }
02724   else
02725   {
02726     return convertNameToFile(m_impl->fileName); 
02727   }
02728 }
02729 
02730 QCString ClassDef::getInstanceOutputFileBase() const 
02731 { 
02732   if (isReference())
02733   {
02734     return m_impl->fileName;
02735   }
02736   else
02737   {
02738     return convertNameToFile(m_impl->fileName); 
02739   }
02740 }
02741 
02742 QCString ClassDef::getFileBase() const 
02743 { 
02744   if (m_impl->templateMaster)
02745   {
02746     return m_impl->templateMaster->getFileBase();
02747   }
02748   else
02749   {
02750     return m_impl->fileName; 
02751   }
02752 }
02753 
02754 QCString ClassDef::getSourceFileBase() const 
02755 { 
02756   if (m_impl->templateMaster)
02757   {
02758     return m_impl->templateMaster->getSourceFileBase();
02759   }
02760   else
02761   {
02762     return convertNameToFile(m_impl->fileName+"-source"); 
02763   }
02764 }
02765 
02766 void ClassDef::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs)
02767 {
02768   gd->addClass(this);
02769   //printf("ClassDef::setGroupDefForAllMembers(%s)\n",gd->name().data());
02770   if (m_impl->allMemberNameInfoSDict==0) return;
02771   MemberNameInfoSDict::Iterator mnili(*m_impl->allMemberNameInfoSDict);
02772   MemberNameInfo *mni;
02773   for (;(mni=mnili.current());++mnili)
02774   {
02775     MemberNameInfoIterator mnii(*mni);
02776     MemberInfo *mi;
02777     for (mnii.toFirst();(mi=mnii.current());++mnii)
02778     {
02779       MemberDef *md=mi->memberDef;
02780       md->setGroupDef(gd,pri,fileName,startLine,hasDocs);
02781       gd->insertMember(md,TRUE);
02782       ClassDef *innerClass = md->getClassDefOfAnonymousType();
02783       if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs);
02784     }
02785   }
02786 }
02787 
02788 void ClassDef::addInnerCompound(Definition *d)
02789 {
02790   //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data());
02791   if (d->definitionType()==Definition::TypeClass) // only classes can be
02792                                                   // nested in classes.
02793   {
02794     if (m_impl->innerClasses==0)
02795     {
02796       m_impl->innerClasses = new ClassSDict(17);
02797     }
02798     m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d);
02799   }
02800 }
02801 
02802 Definition *ClassDef::findInnerCompound(const char *name)
02803 {
02804   Definition *result=0;
02805   if (name==0) return 0;
02806   if (m_impl->innerClasses)
02807   {
02808     result = m_impl->innerClasses->find(name);
02809   }
02810   return result;
02811 }
02812 
02813 //void ClassDef::initTemplateMapping()
02814 //{
02815 //  m_impl->templateMapping->clear();
02816 //  ArgumentList *al = templateArguments();
02817 //  if (al)
02818 //  {
02819 //    ArgumentListIterator ali(*al);
02820 //    Argument *arg;
02821 //    for (ali.toFirst();(arg=ali.current());++ali)
02822 //    {
02823 //      setTemplateArgumentMapping(arg->name,arg->defval);
02824 //    }
02825 //  }
02826 //}
02827 //void ClassDef::setTemplateArgumentMapping(const char *formal,const char *actual)
02828 //{
02829 //  //printf("ClassDef::setTemplateArgumentMapping(%s,%s)\n",formal,actual);
02830 //  if (m_impl->templateMapping && formal)
02831 //  {
02832 //    if (m_impl->templateMapping->find(formal))
02833 //    {
02834 //      m_impl->templateMapping->remove(formal);
02835 //    }
02836 //    m_impl->templateMapping->insert(formal,new QCString(actual));
02837 //  }
02838 //}
02839 //
02840 //QCString ClassDef::getTemplateArgumentMapping(const char *formal) const
02841 //{
02842 //  if (m_impl->templateMapping && formal)
02843 //  {
02844 //    QCString *s = m_impl->templateMapping->find(formal);
02845 //    if (s)
02846 //    {
02847 //      return *s;
02848 //    }
02849 //  }
02850 //  return "";
02851 //}
02852 
02853 ClassDef *ClassDef::insertTemplateInstance(const QCString &fileName,
02854     int startLine, const QCString &templSpec,bool &freshInstance)
02855 {
02856   freshInstance = FALSE;
02857   if (m_impl->templateInstances==0) 
02858   {
02859     m_impl->templateInstances = new QDict<ClassDef>(17);
02860   }
02861   ClassDef *templateClass=m_impl->templateInstances->find(templSpec);
02862   if (templateClass==0)
02863   {
02864     Debug::print(Debug::Classes,0,"      New template instance class `%s'`%s'\n",name().data(),templSpec.data());
02865     templateClass = new ClassDef(
02866         fileName,startLine,localName()+templSpec,ClassDef::Class);
02867     templateClass->setTemplateMaster(this);
02868     templateClass->setOuterScope(getOuterScope());
02869     templateClass->setHidden(isHidden());
02870     m_impl->templateInstances->insert(templSpec,templateClass);
02871     freshInstance=TRUE;
02872   }
02873   return templateClass;
02874 }
02875 
02876 ClassDef *ClassDef::getVariableInstance(const char *templSpec)
02877 {
02878   if (m_impl->variableInstances==0) 
02879   {
02880     m_impl->variableInstances = new QDict<ClassDef>(17);
02881     m_impl->variableInstances->setAutoDelete(TRUE);
02882   }
02883   ClassDef *templateClass=m_impl->variableInstances->find(templSpec);
02884   if (templateClass==0)
02885   {
02886     Debug::print(Debug::Classes,0,"      New template variable instance class `%s'`%s'\n",name().data(),templSpec);
02887     templateClass = new ClassDef("<code>",1,name()+templSpec,
02888                         ClassDef::Class,0,0,FALSE);
02889     templateClass->addMembersToTemplateInstance( this, templSpec );
02890     templateClass->setTemplateMaster(this);
02891     m_impl->variableInstances->insert(templSpec,templateClass);
02892   }
02893   return templateClass;
02894 }
02895 
02896 void ClassDef::setTemplateBaseClassNames(QDict<int> *templateNames)
02897 {
02898   if (templateNames==0) return;
02899   if (m_impl->templBaseClassNames==0)
02900   {
02901     m_impl->templBaseClassNames = new QDict<int>(17);
02902     m_impl->templBaseClassNames->setAutoDelete(TRUE);
02903   }
02904   // make a deep copy of the dictionary.
02905   QDictIterator<int> qdi(*templateNames);
02906   for (;qdi.current();++qdi)
02907   {
02908     if (m_impl->templBaseClassNames->find(qdi.currentKey())==0)
02909     {
02910       m_impl->templBaseClassNames->insert(qdi.currentKey(),new int(*qdi.current()));
02911     }
02912   }
02913 }
02914 
02915 QDict<int> *ClassDef::getTemplateBaseClassNames() const
02916 {
02917   return m_impl->templBaseClassNames;
02918 }
02919 
02920 void ClassDef::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec)
02921 {
02922   //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec);
02923   if (cd->memberNameInfoSDict()==0) return;
02924   MemberNameInfoSDict::Iterator mnili(*cd->memberNameInfoSDict());
02925   MemberNameInfo *mni;
02926   for (;(mni=mnili.current());++mnili)
02927   {
02928     MemberNameInfoIterator mnii(*mni);
02929     MemberInfo *mi;
02930     for (mnii.toFirst();(mi=mnii.current());++mnii)
02931     {
02932       ArgumentList *actualArguments = new ArgumentList;
02933       stringToArgumentList(templSpec,actualArguments);
02934       MemberDef *md = mi->memberDef;
02935       MemberDef *imd = md->createTemplateInstanceMember(
02936                           cd->templateArguments(),actualArguments);
02937       delete actualArguments;
02938       //printf("%s->setMemberClass(%p)\n",imd->name().data(),this);
02939       imd->setMemberClass(this);
02940       imd->setTemplateMaster(md);
02941       imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
02942       imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
02943       imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
02944       imd->setMemberSpecifiers(md->getMemberSpecifiers());
02945       imd->setMemberGroupId(md->getMemberGroupId());
02946       insertMember(imd);
02947       //printf("Adding member=%s %s%s to class %s templSpec %s\n",
02948       //    imd->typeString(),imd->name().data(),imd->argsString(),
02949       //    imd->getClassDef()->name().data(),templSpec);
02950       // insert imd in the list of all members
02951       //printf("Adding member=%s class=%s\n",imd->name().data(),name().data());
02952       MemberName *mn = Doxygen::memberNameSDict->find(imd->name());
02953       if (mn==0)
02954       {
02955         mn = new MemberName(imd->name());
02956         Doxygen::memberNameSDict->append(imd->name(),mn);
02957       }
02958       mn->append(imd);
02959     }
02960   }
02961 }
02962 
02963 QCString ClassDef::getReference() const
02964 {
02965   if (m_impl->templateMaster)
02966   {
02967     return m_impl->templateMaster->getReference();
02968   }
02969   else
02970   {
02971     return Definition::getReference();
02972   }
02973 }
02974 
02975 bool ClassDef::isReference() const
02976 {
02977   if (m_impl->templateMaster)
02978   {
02979     return m_impl->templateMaster->isReference();
02980   }
02981   else
02982   {
02983     return Definition::isReference();
02984   }
02985 }
02986 
02987 void ClassDef::getTemplateParameterLists(QList<ArgumentList> &lists) const
02988 {
02989   Definition *d=getOuterScope();
02990   if (d)
02991   {
02992     if (d->definitionType()==Definition::TypeClass)
02993     {
02994       ClassDef *cd=(ClassDef *)d;
02995       cd->getTemplateParameterLists(lists);
02996     }
02997   }
02998   if (templateArguments())
02999   {
03000     lists.append(templateArguments());
03001   }
03002 }
03003 
03004 QCString ClassDef::qualifiedNameWithTemplateParameters(
03005     QList<ArgumentList> *actualParams) const
03006 {
03007   static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
03008   //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data());
03009   QCString scName;
03010   Definition *d=getOuterScope();
03011   if (d)
03012   {
03013     if (d->definitionType()==Definition::TypeClass)
03014     {
03015       ClassDef *cd=(ClassDef *)d;
03016       scName = cd->qualifiedNameWithTemplateParameters(actualParams);
03017     }
03018     else
03019     {
03020       scName = d->qualifiedName();
03021     }
03022   }
03023 
03024   QCString scopeSeparator;
03025   if (optimizeOutputJava)
03026     scopeSeparator=".";
03027   else
03028     scopeSeparator="::";
03029 
03030   if (!scName.isEmpty()) scName+=scopeSeparator;
03031   scName+=localName();
03032   ArgumentList *al=0;
03033   bool isSpecialization = localName().find('<')!=-1;
03034   if (templateArguments())
03035   {
03036     if (actualParams && (al=actualParams->current()))
03037     {
03038       if (!isSpecialization)
03039       {
03040         scName+=tempArgListToString(al);
03041       }
03042       actualParams->next();
03043     }
03044     else
03045     {
03046       if (!isSpecialization)
03047       {
03048         scName+=tempArgListToString(templateArguments());
03049       }
03050     }
03051   }
03052   //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data());
03053   return scName;
03054 }
03055 
03056 QCString ClassDef::className() const
03057 {
03058   return m_impl->className;
03059 };
03060 
03061 void ClassDef::setClassName(const char *name)
03062 {
03063   m_impl->className = name;
03064 }
03065 
03066 void ClassDef::addListReferences()
03067 {
03068   bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN");
03069   if (!isLinkableInProject()) return;
03070   //printf("ClassDef(%s)::addListReferences()\n",name().data());
03071   {
03072     LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems();
03073     addRefItem(xrefItems.pointer(),
03074              fortranOpt?theTranslator->trType(TRUE,TRUE):theTranslator->trClass(TRUE,TRUE),
03075              getOutputFileBase(),displayName()
03076             );
03077   }
03078   if (m_impl->memberGroupSDict)
03079   {
03080     MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
03081     MemberGroup *mg;
03082     for (;(mg=mgli.current());++mgli)
03083     {
03084       mg->addListReferences(this);
03085     }
03086   }
03087   QListIterator<MemberList> mli(m_impl->memberLists);
03088   MemberList *ml;
03089   for (mli.toFirst();(ml=mli.current());++mli)
03090   {
03091     if (ml->listType()&MemberList::detailedLists)
03092     {
03093       ml->addListReferences(this);
03094     }
03095   }
03096 }
03097 
03098 MemberDef *ClassDef::getMemberByName(const QCString &name) const
03099 {
03100   MemberDef *xmd = 0;
03101   if (m_impl->allMemberNameInfoSDict)
03102   {
03103     MemberNameInfo *mni = m_impl->allMemberNameInfoSDict->find(name);
03104     if (mni)
03105     {
03106       const int maxInheritanceDepth = 100000;
03107       int mdist=maxInheritanceDepth;
03108       MemberNameInfoIterator mnii(*mni);
03109       MemberInfo *mi;
03110       for (mnii.toFirst();(mi=mnii.current());++mnii)
03111       {
03112         ClassDef *mcd=mi->memberDef->getClassDef();
03113         int m=minClassDistance(this,mcd);
03114         //printf("found member in %s linkable=%d m=%d\n",
03115         //    mcd->name().data(),mcd->isLinkable(),m);
03116         if (m<mdist && mcd->isLinkable())
03117         {
03118           mdist=m;
03119           xmd=mi->memberDef;
03120         }
03121       }
03122     }
03123   }
03124   //printf("getMemberByName(%s)=%p\n",name.data(),xmd);
03125   return xmd;
03126 }
03127 
03128 bool ClassDef::isAccessibleMember(MemberDef *md)
03129 {
03130   return md->getClassDef() && isBaseClass(md->getClassDef(),TRUE);
03131 }
03132 
03133 MemberList *ClassDef::createMemberList(MemberList::ListType lt)
03134 {
03135   m_impl->memberLists.setAutoDelete(TRUE);
03136   QListIterator<MemberList> mli(m_impl->memberLists);
03137   MemberList *ml;
03138   for (mli.toFirst();(ml=mli.current());++mli)
03139   {
03140     if (ml->listType()==lt)
03141     {
03142       return ml;
03143     }
03144   }
03145   // not found, create a new member list
03146   ml = new MemberList(lt);
03147   m_impl->memberLists.append(ml);
03148   return ml;
03149 }
03150 
03151 MemberList *ClassDef::getMemberList(MemberList::ListType lt)
03152 {
03153   MemberList *ml = m_impl->memberLists.first();
03154   while (ml)
03155   {
03156     if (ml->listType()==lt)
03157     {
03158       return ml;
03159     }
03160     ml = m_impl->memberLists.next();
03161   }
03162   return 0;
03163 }
03164 
03165 void ClassDef::addMemberToList(MemberList::ListType lt,MemberDef *md)
03166 {
03167   static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS");
03168   MemberList *ml = createMemberList(lt);
03169   if (sortBriefDocs)
03170     ml->inSort(md);
03171   else
03172     ml->append(md);
03173 
03174   // for members in the declaration lists we set the section, needed for member grouping
03175   if ((ml->listType()&MemberList::detailedLists)==0) md->setSectionList(this,ml);
03176 }
03177 
03178 void ClassDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title,
03179                const char *subTitle)
03180 {
03181   static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
03182   MemberList * ml = getMemberList(lt);
03183   if (ml) 
03184   {
03185     if (optimizeVhdl) // use specific declarations function
03186     {
03187       VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this);
03188     }
03189     else // ise generic declaration function
03190     {
03191       ml->writeDeclarations(ol,this,0,0,0,title,subTitle); 
03192     }
03193   }
03194 }
03195 
03196 void ClassDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title)
03197 {
03198   MemberList * ml = getMemberList(lt);
03199   if (ml) ml->writeDocumentation(ol,name(),this,title);
03200 }
03201 
03202 void ClassDef::writePlainMemberDeclaration(OutputList &ol,MemberList::ListType lt,bool inGroup)
03203 {
03204   MemberList * ml = getMemberList(lt);
03205   if (ml) 
03206   {
03207     ml->setInGroup(inGroup);
03208     ml->writePlainDeclarations(ol,this,0,0,0); 
03209   }
03210 }
03211 
03212 bool ClassDef::isLocal() const 
03213 { 
03214   return m_impl->isLocal; 
03215 }
03216 
03217 ClassSDict *ClassDef::getInnerClasses() 
03218 { 
03219   return m_impl->innerClasses; 
03220 }
03221 
03222 ClassDef::CompoundType ClassDef::compoundType() const 
03223 { 
03224   return m_impl->compType; 
03225 } 
03226 
03227 BaseClassList *ClassDef::baseClasses() const
03228 { 
03229   return m_impl->inherits; 
03230 }
03231 
03232 BaseClassList *ClassDef::subClasses() const
03233 { 
03234   return m_impl->inheritedBy; 
03235 }
03236 
03237 MemberNameInfoSDict *ClassDef::memberNameInfoSDict() const
03238 { 
03239   return m_impl->allMemberNameInfoSDict; 
03240 }
03241 
03242 Protection ClassDef::protection() const 
03243 { 
03244   return m_impl->prot; 
03245 }
03246 
03247 ArgumentList *ClassDef::templateArguments() const 
03248 { 
03249   return m_impl->tempArgs; 
03250 }
03251 
03252 NamespaceDef *ClassDef::getNamespaceDef() const
03253 { 
03254   return m_impl->nspace; 
03255 }
03256 
03257 FileDef *ClassDef::getFileDef() const 
03258 { 
03259   return m_impl->fileDef; 
03260 }
03261 
03262 QDict<ClassDef> *ClassDef::getTemplateInstances() const 
03263 { 
03264   return m_impl->templateInstances; 
03265 }
03266 
03267 ClassDef *ClassDef::templateMaster() const 
03268 { 
03269   return m_impl->templateMaster; 
03270 } 
03271 
03272 bool ClassDef::isTemplate() const 
03273 { 
03274   return m_impl->tempArgs!=0; 
03275 }
03276 
03277 IncludeInfo *ClassDef::includeInfo() const 
03278 { 
03279   return m_impl->incInfo; 
03280 }
03281 
03282 UsesClassDict *ClassDef::usedImplementationClasses() const 
03283 { 
03284   return m_impl->usesImplClassDict; 
03285 }
03286 
03287 UsesClassDict *ClassDef::usedByImplementationClasses() const 
03288 { 
03289   return m_impl->usedByImplClassDict; 
03290 }
03291 
03292 UsesClassDict *ClassDef::usedInterfaceClasses() const
03293 {
03294   return m_impl->usesIntfClassDict;
03295 }
03296 
03297 bool ClassDef::isTemplateArgument() const
03298 {
03299   return m_impl->isTemplArg;
03300 }
03301 
03302 bool ClassDef::isAbstract() const 
03303 { 
03304   return m_impl->isAbstract; 
03305 }
03306 
03307 bool ClassDef::isObjectiveC() const 
03308 { 
03309   return m_impl->isObjC; 
03310 }
03311 
03312 ClassDef *ClassDef::categoryOf() const 
03313 { 
03314   return m_impl->categoryOf; 
03315 }
03316 
03317 const QList<MemberList> &ClassDef::getMemberLists() const 
03318 { 
03319   return m_impl->memberLists; 
03320 }
03321 
03322 MemberGroupSDict *ClassDef::getMemberGroupSDict() const 
03323 { 
03324   return m_impl->memberGroupSDict; 
03325 }
03326 
03327 void ClassDef::setNamespace(NamespaceDef *nd) 
03328 { 
03329   m_impl->nspace = nd; 
03330 }
03331 
03332 void ClassDef::setFileDef(FileDef *fd) 
03333 { 
03334   m_impl->fileDef=fd; 
03335 }
03336 
03337 void ClassDef::setSubGrouping(bool enabled) 
03338 { 
03339   m_impl->subGrouping = enabled; 
03340 }
03341 
03342 void ClassDef::setProtection(Protection p) 
03343 { 
03344   m_impl->prot=p; 
03345 }
03346 
03347 void ClassDef::setIsStatic(bool b) 
03348 { 
03349   m_impl->isStatic=b; 
03350 }
03351 
03352 void ClassDef::setIsObjectiveC(bool b) 
03353 { 
03354   m_impl->isObjC=b; 
03355 }
03356 
03357 void ClassDef::setCompoundType(CompoundType t) 
03358 { 
03359   m_impl->compType = t; 
03360 } 
03361 
03362 void ClassDef::setTemplateMaster(ClassDef *tm) 
03363 { 
03364   m_impl->templateMaster=tm; 
03365 }
03366 
03367 void ClassDef::makeTemplateArgument(bool b) 
03368 { 
03369   m_impl->isTemplArg = b; 
03370 }
03371 
03372 void ClassDef::setCategoryOf(ClassDef *cd)
03373 {
03374   m_impl->categoryOf = cd;
03375 }
03376 
03377 void ClassDef::setUsedOnly(bool b)
03378 {
03379   m_impl->usedOnly = b;
03380 }
03381 
03382 bool ClassDef::isUsedOnly() const
03383 {
03384   return m_impl->usedOnly;
03385 }
03386 



Generated on Mon Mar 31 10:58:32 2008 by  doxygen 1.5.1