e19ceada06ce844543deeda5f2443dbe3aa950e6
[platform/upstream/doxygen.git] / src / memberlist.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #include <qregexp.h>
19
20 #include "memberlist.h"
21 #include "classdef.h"
22 #include "message.h"
23 #include "util.h"
24 #include "language.h"
25 #include "doxygen.h"
26 #include "outputlist.h"
27 #include "groupdef.h"
28 #include "marshal.h"
29 #include "vhdldocgen.h"
30 #include "namespacedef.h"
31 #include "filedef.h"
32 #include "membergroup.h"
33 #include "config.h"
34 #include "docparser.h"
35
36 MemberList::MemberList() : m_listType(MemberListType_pubMethods)
37 {
38   memberGroupList=0;
39   m_varCnt=0;
40   m_funcCnt=0;
41   m_enumCnt=0;
42   m_enumValCnt=0;
43   m_typeCnt=0;
44   m_protoCnt=0;
45   m_defCnt=0;
46   m_friendCnt=0;
47   m_numDecMembers=-1; // special value indicating that value needs to be computed
48   m_numDocMembers=-1; // special value indicating that value needs to be computed
49   m_inGroup=FALSE;
50   m_inFile=FALSE;
51   m_needsSorting=FALSE;
52 }
53
54 MemberList::MemberList(MemberListType lt) : m_listType(lt)
55 {
56   memberGroupList=0;
57   m_varCnt=0;
58   m_funcCnt=0;
59   m_enumCnt=0;
60   m_enumValCnt=0;
61   m_typeCnt=0;
62   m_protoCnt=0;
63   m_defCnt=0;
64   m_friendCnt=0;
65   m_numDecMembers=-1; // special value indicating that value needs to be computed
66   m_numDocMembers=-1; // special value indicating that value needs to be computed
67   m_inGroup=FALSE;
68   m_inFile=FALSE;
69   m_needsSorting=FALSE;
70 }
71
72 MemberList::~MemberList()
73 {
74   delete memberGroupList;
75 }
76
77 int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
78 {
79   static bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
80   if (sortConstructorsFirst) {
81     int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0);
82     int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0);
83     if (ord1 > ord2)
84       return -1;
85     else if (ord2 > ord1)
86       return 1;
87   }
88   int cmp = qstricmp(c1->name(),c2->name());
89   return cmp!=0 ? cmp : c1->getDefLine()-c2->getDefLine();
90 }
91
92 int MemberList::countInheritableMembers(ClassDef *inheritedFrom) const
93 {
94   int count=0;
95   QListIterator<MemberDef> mli(*this);
96   MemberDef *md;
97   for (mli.toFirst();(md=mli.current());++mli)
98   {
99     if (md->isBriefSectionVisible())
100     {
101       if (md->memberType()!=MemberType_Friend &&
102           md->memberType()!=MemberType_EnumValue)
103       {
104         //printf("member %s: isReimplementedBy(%s)=%d\n",md->name().data(),
105         //    inheritedFrom->name().data(),
106         //    md->isReimplementedBy(inheritedFrom));
107         if (md->memberType()==MemberType_Function)
108         {
109           if (!md->isReimplementedBy(inheritedFrom)) count++;
110         }
111         else
112         {
113           count++;
114         }
115       }
116     }
117   }
118   if (memberGroupList)
119   {
120     MemberGroupListIterator mgli(*memberGroupList);
121     MemberGroup *mg;
122     for (;(mg=mgli.current());++mgli)
123     {
124       count+=mg->countInheritableMembers(inheritedFrom);
125     }
126   }
127   //printf("%s::countInheritableMembers(%s)=%d\n",
128   //    listTypeAsString().data(),
129   //    inheritedFrom->name().data(),count);
130   return count;
131 }
132
133 /*! Count the number of members in this list that are visible in
134  *  the declaration part of a compound's documentation page.
135  */
136 void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
137 {
138   if (m_numDecMembers!=-1) return; 
139   
140   //printf("----- countDecMembers count=%d ----\n",count());
141   m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
142   m_typeCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
143   m_numDecMembers=0;
144   QListIterator<MemberDef> mli(*this);
145   MemberDef *md;
146   for (mli.toFirst();(md=mli.current());++mli)
147   {
148     //printf("MemberList::countDecMembers(md=%s,%d)\n",md->name().data(),md->isBriefSectionVisible());
149     if (md->isBriefSectionVisible())
150     {
151       switch(md->memberType())
152       {
153         case MemberType_Variable:    // fall through
154         case MemberType_Event:       // fall through
155         case MemberType_Property:    m_varCnt++,m_numDecMembers++;  
156                                      break;
157 // apparently necessary to get this to show up in declarations section?
158         case MemberType_Interface:   // fall through
159         case MemberType_Service:     // fall through
160         case MemberType_Function:    // fall through
161         case MemberType_Signal:      // fall through
162         case MemberType_DCOP:        // fall through
163         case MemberType_Slot:        if (!md->isRelated() || md->getClassDef())
164                                        m_funcCnt++,m_numDecMembers++; 
165                                      break;
166         case MemberType_Enumeration: m_enumCnt++,m_numDecMembers++; break;
167         case MemberType_EnumValue:   if (countEnumValues)
168                                        m_enumValCnt++,m_numDecMembers++; 
169                                      break;
170         case MemberType_Typedef:     m_typeCnt++,m_numDecMembers++; break;
171         //case MemberType_Prototype:   m_protoCnt++,m_numDecMembers++; break;
172         case MemberType_Define:      if (Config_getBool(EXTRACT_ALL) || 
173                                          md->argsString() || 
174                                          !md->initializer().isEmpty() ||
175                                          md->hasDocumentation() 
176                                         ) m_defCnt++,m_numDecMembers++;     
177                                      break;
178         case MemberType_Friend:      m_friendCnt++,m_numDecMembers++;  
179                                      break;
180         default:
181           err("Unknown member type found for member `%s'\n!",md->name().data());
182       }
183     }
184   }
185   if (memberGroupList)
186   {
187     MemberGroupListIterator mgli(*memberGroupList);
188     MemberGroup *mg;
189     for (;(mg=mgli.current());++mgli)
190     {
191       mg->countDecMembers(gd);
192       m_varCnt+=mg->varCount();
193       m_funcCnt+=mg->funcCount();
194       m_enumCnt+=mg->enumCount();
195       m_enumValCnt+=mg->enumValueCount();
196       m_typeCnt+=mg->typedefCount();
197       m_protoCnt+=mg->protoCount();
198       m_defCnt+=mg->defineCount();
199       m_friendCnt+=mg->friendCount();
200       m_numDecMembers+=mg->numDecMembers();
201     }
202   }
203   //printf("----- end countDecMembers ----\n");
204
205   //printf("MemberList::countDecMembers()=%d\n",m_numDecMembers);
206 }
207
208 void MemberList::countDocMembers(bool countEnumValues)
209 {
210   if (m_numDocMembers!=-1) return; // used cached value
211   m_numDocMembers=0;
212   QListIterator<MemberDef> mli(*this);
213   MemberDef *md;
214   for (mli.toFirst();(md=mli.current());++mli)
215   {
216     if (md->isDetailedSectionVisible(m_inGroup,m_inFile)) 
217     {
218       // do not count enum values, since they do not produce entries of their own
219       if (countEnumValues || md->memberType()!=MemberType_EnumValue) 
220         m_numDocMembers++;
221     }
222   }
223   if (memberGroupList)
224   {
225     MemberGroupListIterator mgli(*memberGroupList);
226     MemberGroup *mg;
227     for (;(mg=mgli.current());++mgli)
228     {
229       mg->countDocMembers();
230       m_numDocMembers+=mg->numDocMembers();
231     }
232   }
233   //printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList);
234 }
235
236 void MemberList::inSort(const MemberDef *md)
237 {
238   QList<MemberDef>::inSort(md);
239 }
240
241 void MemberList::append(const MemberDef *md)
242 {
243   QList<MemberDef>::append(md);
244 }
245
246 void MemberList::remove(const MemberDef *md)
247 {
248   QList<MemberDef>::remove(md);
249 }
250
251 void MemberList::sort()
252 {
253   QList<MemberDef>::sort();
254 }
255
256 uint MemberList::count() const
257 {
258   return QList<MemberDef>::count();
259 }
260
261 int MemberList::findRef(const MemberDef *md) const
262 {
263   return QList<MemberDef>::findRef(md);
264 }
265
266 MemberDef *MemberList::getFirst() const
267 {
268   return QList<MemberDef>::getFirst();
269 }
270
271 MemberDef *MemberList::take(uint index)
272 {
273   return QList<MemberDef>::take(index);
274 }
275
276 MemberListIterator::MemberListIterator(const MemberList &l) :
277   QListIterator<MemberDef>(l) 
278 {
279 }
280
281 int MemberList::countEnumValues(MemberDef *md,bool setAnonEnumType) const
282 {
283   int enumVars=0;
284   MemberListIterator vmli(*this);
285   MemberDef *vmd;
286   QCString name(md->name());
287   int i=name.findRev("::");
288   if (i!=-1) name=name.right(name.length()-i-2); // strip scope (TODO: is this needed?)
289   if (name[0]=='@') // anonymous enum => append variables
290   {
291     for ( ; (vmd=vmli.current()) ; ++vmli)
292     {
293       QCString vtype=vmd->typeString();
294       if ((vtype.find(name))!=-1) 
295       {
296         enumVars++;
297         if (setAnonEnumType)
298         {
299           vmd->setAnonymousEnumType(md);
300         }
301       }
302     }
303   }
304   return enumVars;
305 }
306
307 bool MemberList::declVisible() const
308 {
309   MemberListIterator mli(*this);
310   MemberDef *md;
311   for ( ; (md=mli.current()); ++mli )
312   {
313     if (md->isBriefSectionVisible())
314     {
315       switch (md->memberType())
316       {
317         case MemberType_Define:    // fall through
318         case MemberType_Typedef:   // fall through
319         case MemberType_Variable:  // fall through
320         case MemberType_Function:  // fall through
321         case MemberType_Signal:    // fall through
322         case MemberType_Slot:      // fall through
323         case MemberType_DCOP:      // fall through
324         case MemberType_Property:  // fall through
325         case MemberType_Interface: // fall through
326         case MemberType_Service:   // fall through
327         case MemberType_Event:  
328           return TRUE;
329         case MemberType_Enumeration: 
330           {
331             // if this is an anonymous enum and there are variables of this
332             // enum type (i.e. enumVars>0), then we do not show the enum here.
333             if (countEnumValues(md,FALSE)==0) // show enum here
334             {
335               return TRUE;
336             }
337           }
338           break;
339         case MemberType_Friend:
340           return TRUE;
341         case MemberType_EnumValue: 
342           {
343             if (m_inGroup)
344             {
345               return TRUE;
346             }
347           }
348           break;
349       }
350     }
351   }
352   return FALSE;
353 }
354
355 void MemberList::writePlainDeclarations(OutputList &ol,
356                        ClassDef *cd,NamespaceDef *nd,FileDef *fd,
357                        GroupDef *gd,ClassDef *inheritedFrom,const char *inheritId
358                       )
359 {
360   //printf("----- writePlainDeclaration() ----\n");
361   static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
362   countDecMembers();
363   if (numDecMembers()==0) 
364   {
365     //printf("  --> no members!\n");
366     return; // no members in this list
367   }
368   //printf("  --> writePlainDeclaration() numDecMembers()=%d\n",
369   //    numDecMembers());
370   
371   ol.pushGeneratorState();
372
373   bool first=TRUE;
374   MemberDef *md;
375   MemberListIterator mli(*this);
376   for ( ; (md=mli.current()); ++mli )
377   {
378     //printf(">>> Member `%s' type=%d visible=%d\n",
379     //    md->name().data(),md->memberType(),md->isBriefSectionVisible());
380     if ((inheritedFrom==0 || !md->isReimplementedBy(inheritedFrom)) &&
381         md->isBriefSectionVisible())
382     {
383       //printf(">>> rendering\n");
384       switch(md->memberType())
385       {
386         case MemberType_Define:    // fall through
387         //case MemberType_Prototype: // fall through
388         case MemberType_Typedef:   // fall through
389         case MemberType_Variable:  // fall through
390         case MemberType_Function:  // fall through
391         case MemberType_Signal:    // fall through
392         case MemberType_Slot:      // fall through
393         case MemberType_DCOP:      // fall through
394         case MemberType_Property:  // fall through
395         case MemberType_Interface: // fall through
396         case MemberType_Service:   // fall through
397         case MemberType_Event:  
398           {
399             if (first) ol.startMemberList(),first=FALSE;
400             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
401             break;
402           }
403         case MemberType_Enumeration: 
404           {
405             // if this is an anonymous enum and there are variables of this
406             // enum type (i.e. enumVars>0), then we do not show the enum here.
407             if (countEnumValues(md,TRUE)==0) // show enum here
408             {
409               //printf("Enum!!\n");
410               if (first)
411               {
412                 ol.startMemberList();
413                 first=FALSE;
414               }
415               ol.startMemberDeclaration();
416               ol.startMemberItem(md->anchor(),0,inheritId);
417               bool detailsLinkable = md->isDetailedSectionLinkable();
418               if (!detailsLinkable)
419               {
420                 ol.startDoxyAnchor(md->getOutputFileBase(),0,md->anchor(),md->name(),QCString());
421               }
422               ol.writeString("enum ");
423               ol.insertMemberAlign();
424               md->writeEnumDeclaration(ol,cd,nd,fd,gd);
425               if (!detailsLinkable)
426               {
427                 ol.endDoxyAnchor(md->getOutputFileBase(),md->anchor());
428               }
429               ol.endMemberItem();
430               if (!md->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
431               {
432                 DocRoot *rootNode = validatingParseDoc(
433                     md->briefFile(),md->briefLine(),
434                     cd,md,
435                     md->briefDescription(),
436                     TRUE,FALSE,0,TRUE,FALSE
437                     );
438                 if (rootNode && !rootNode->isEmpty())
439                 {
440                   ol.startMemberDescription(md->anchor());
441                   ol.writeDoc(rootNode,cd,md);
442                   if (md->isDetailedSectionLinkable())
443                   {
444                     ol.disableAllBut(OutputGenerator::Html);
445                     ol.docify(" ");
446                     ol.startTextLink(md->getOutputFileBase(),
447                         md->anchor());
448                     ol.parseText(theTranslator->trMore());
449                     ol.endTextLink();
450                     ol.enableAll();
451                   }
452                   ol.endMemberDescription();
453                 }
454                 delete rootNode;
455               }
456               ol.endMemberDeclaration(md->anchor(),inheritId);
457             }
458             md->warnIfUndocumented();
459             break;
460           }
461         case MemberType_Friend:
462           if (inheritedFrom==0)
463           {
464             if (first) 
465             {
466               ol.startMemberList();
467               first=FALSE;
468             }
469             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
470             break;
471           }
472         case MemberType_EnumValue: 
473           {
474             if (m_inGroup)
475             {
476               //printf("EnumValue!\n");
477               if (first) ol.startMemberList(),first=FALSE;
478               md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
479             }
480           }
481           break;
482       }
483     }
484   }
485
486   // handle members that are inside anonymous compounds and for which
487   // no variables of the anonymous compound type exist.
488   if (cd)
489   {
490     MemberListIterator mli(*this);
491     for  ( ; (md=mli.current()) ; ++mli )
492     {
493       if (md->fromAnonymousScope() && !md->anonymousDeclShown())
494       {
495         md->setFromAnonymousScope(FALSE);
496         //printf("anonymous compound members\n");
497         if (md->isBriefSectionVisible())
498         {
499           if (first) 
500           {
501             ol.startMemberList();
502             first=FALSE;
503           }
504           md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup);
505         }
506         md->setFromAnonymousScope(TRUE);
507       }
508     }
509   }
510  
511   if (!first) 
512   {
513     ol.endMemberList(); 
514   }
515
516   ol.popGeneratorState();
517   //printf("----- end writePlainDeclaration() ----\n");
518 }
519
520 /** Writes the list of members to the output.
521  *  @param ol Output list to write to
522  *  @param cd non-null if this list is part of class documentation.
523  *  @param nd non-null if this list is part of namespace documentation.
524  *  @param fd non-null if this list is part of file documentation.
525  *  @param gd non-null if this list is part of group documentation.
526  *  @param title Title to use for the member list.
527  *  @param subtitle Sub title to use for the member list.
528  *  @param showEnumValues Obsolete, always set to FALSE.
529  *  @param showInline if set to TRUE if title is rendered differently
530  *  @param inheritedFrom if not 0, the list is shown inside the
531  *         given class as inherited members, parameter cd points to the
532  *         class containing the members.
533  *  @param lt Type of list that is inherited from.
534  */
535 void MemberList::writeDeclarations(OutputList &ol,
536              ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
537              const char *title,const char *subtitle, bool showEnumValues,
538              bool showInline,ClassDef *inheritedFrom,MemberListType lt)
539 {
540   (void)showEnumValues; // unused
541
542   //printf("----- writeDeclaration() this=%p ---- inheritedFrom=%p\n",this,inheritedFrom);
543   static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
544   QCString inheritId;
545
546   countDecMembers(/*showEnumValues*/FALSE,gd); // count members shown in this section
547   Definition *ctx = cd;
548   if (ctx==0 && nd) ctx = nd;
549   if (ctx==0 && gd) ctx = gd;
550   if (ctx==0 && fd) ctx = fd;
551
552   //printf("%p: MemberList::writeDeclaration(title=`%s',subtitle=`%s')=%d inheritedFrom=%p\n",
553   //       this,title,subtitle,numDecMembers(),inheritedFrom);
554
555   int num = numDecMembers();
556   if (inheritedFrom)
557   {
558     //if ( cd && !optimizeVhdl && countInheritableMembers(inheritedFrom)>0 )
559     if ( cd && !optimizeVhdl && cd->countMembersIncludingGrouped(
560                                       m_listType,inheritedFrom,TRUE)>0 )
561     {
562       ol.pushGeneratorState();
563       ol.disableAllBut(OutputGenerator::Html);
564       inheritId = substitute(listTypeAsString(lt),"-","_")+"_"+
565                   stripPath(cd->getOutputFileBase());
566       if (title)
567       {
568         ol.writeInheritedSectionTitle(inheritId,cd->getReference(),
569                                       cd->getOutputFileBase(), 
570                                       cd->anchor(),title,cd->displayName());
571       }
572       ol.popGeneratorState();
573     }
574   }
575   else if (num>0)
576   {
577     if (title) 
578     {
579       if (showInline)
580       {
581         ol.startInlineHeader();
582       }
583       else
584       {
585         ol.startMemberHeader(listTypeAsString(m_listType));
586       }
587       ol.parseText(title);
588       if (showInline)
589       {
590         ol.endInlineHeader();
591       }
592       else
593       {
594         ol.endMemberHeader();
595       }
596     }
597     if (subtitle) 
598     {
599       QCString st=subtitle;
600       st = st.stripWhiteSpace();
601       if (!st.isEmpty())
602       {
603         ol.startMemberSubtitle();
604         ol.generateDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE,0,FALSE,FALSE);
605         ol.endMemberSubtitle();
606       }
607     }
608   }
609   if (num>0)
610   {
611     // TODO: Two things need to be worked out for proper VHDL output:
612     // 1. Signals and types under the group need to be
613     //    formatted to associate them with the group somehow
614     //    indentation, or at the very least, extra space after
615     //    the group is done
616     // 2. This might need to be repeated below for memberGroupLists
617     if (optimizeVhdl) // use specific declarations function
618     {
619       VhdlDocGen::writeVhdlDeclarations(this,ol,0,cd,0,0);
620     }
621     else
622     {
623       writePlainDeclarations(ol,cd,nd,fd,gd,inheritedFrom,inheritId);
624     }
625
626     //printf("memberGroupList=%p\n",memberGroupList);
627     if (memberGroupList)
628     {
629       MemberGroupListIterator mgli(*memberGroupList);
630       MemberGroup *mg;
631       while ((mg=mgli.current()))
632       {
633         bool hasHeader=!mg->header().isEmpty() && mg->header()!="[NOHEADER]";
634         if (inheritId.isEmpty())
635         {
636           //printf("mg->header=%s hasHeader=%d\n",mg->header().data(),hasHeader);
637           ol.startMemberGroupHeader(hasHeader);
638           if (hasHeader)
639           {
640             ol.parseText(mg->header());
641           }
642           ol.endMemberGroupHeader();
643           if (!mg->documentation().isEmpty())
644           {
645             //printf("Member group has docs!\n");
646             ol.startMemberGroupDocs();
647             ol.generateDoc(mg->docFile(),mg->docLine(),ctx,0,mg->documentation()+"\n",FALSE,FALSE);
648             ol.endMemberGroupDocs();
649           }
650           ol.startMemberGroup();
651         }
652         //printf("--- mg->writePlainDeclarations ---\n");
653         mg->writePlainDeclarations(ol,cd,nd,fd,gd,inheritedFrom,inheritId);
654         if (inheritId.isEmpty())
655         {
656           ol.endMemberGroup(hasHeader);
657         }
658         ++mgli;
659       }
660     }
661   }
662   if (inheritedFrom && cd) 
663   {
664     // also add members that of this list type, that are grouped together
665     // in a separate list in class 'inheritedFrom'
666     cd->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId);
667   }
668   //printf("----- end writeDeclaration() ----\n");
669 }
670
671 void MemberList::writeDocumentation(OutputList &ol,
672                      const char *scopeName, Definition *container,
673                      const char *title,bool showEnumValues,bool showInline)
674 {
675   //printf("MemberList::writeDocumentation()\n");
676
677   countDocMembers(showEnumValues);
678   if (numDocMembers()==0) return;
679
680   if (title)
681   {
682     ol.pushGeneratorState();
683       ol.disable(OutputGenerator::Html);
684       ol.writeRuler();
685     ol.popGeneratorState();
686     ol.startGroupHeader(showInline ? 2 : 0);
687     ol.parseText(title);
688     ol.endGroupHeader(showInline ? 2 : 0);
689   }
690   ol.startMemberDocList();
691
692   MemberListIterator mli(*this);
693   MemberDef *md;
694
695   // count the number of overloaded members
696   QDict<uint> overloadTotalDict(67);
697   QDict<uint> overloadCountDict(67);
698   overloadTotalDict.setAutoDelete(TRUE);
699   overloadCountDict.setAutoDelete(TRUE);
700   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
701   {
702     if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
703         !(md->isEnumValue() && !showInline))
704     {
705       uint *pCount = overloadTotalDict.find(md->name());
706       if (pCount)
707       {
708         (*pCount)++;
709       }
710       else
711       {
712         overloadTotalDict.insert(md->name(),new uint(1));
713         overloadCountDict.insert(md->name(),new uint(1));
714       }
715     }
716   }
717
718   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
719   {
720     if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
721         !(md->isEnumValue() && !showInline))
722     {
723       uint overloadCount = *overloadTotalDict.find(md->name());
724       uint *pCount = overloadCountDict.find(md->name());
725       md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,
726           m_inGroup,showEnumValues,showInline);
727       (*pCount)++;
728     }
729   }
730   if (memberGroupList)
731   {
732     printf("MemberList::writeDocumentation()  --  member groups %d\n",memberGroupList->count());
733     MemberGroupListIterator mgli(*memberGroupList);
734     MemberGroup *mg;
735     for (;(mg=mgli.current());++mgli)
736     {
737       mg->writeDocumentation(ol,scopeName,container,showEnumValues,showInline);
738     }
739   }
740   ol.endMemberDocList();
741 }
742
743 // members in a table
744 void MemberList::writeSimpleDocumentation(OutputList &ol,
745                      Definition *container)
746 {
747   countDocMembers(FALSE);
748   //printf("MemberList count=%d\n",numDocMembers());
749   if (numDocMembers()==0) return;
750
751   ClassDef *cd = 0;
752   if (container && container->definitionType()==Definition::TypeClass)
753   {
754     cd = (ClassDef*)container;
755   }
756   ol.startMemberDocSimple(cd && cd->isJavaEnum());
757   MemberListIterator mli(*this);
758   MemberDef *md;
759   for ( ; (md=mli.current()) ; ++mli)
760   {
761     md->writeMemberDocSimple(ol,container);
762   }
763   ol.endMemberDocSimple(cd && cd->isJavaEnum());
764 }
765
766 // separate member pages
767 void MemberList::writeDocumentationPage(OutputList &ol,
768                      const char *scopeName, Definition *container)
769 {
770   static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
771
772   // count the number of overloaded members
773   QDict<uint> overloadTotalDict(67);
774   QDict<uint> overloadCountDict(67);
775   overloadTotalDict.setAutoDelete(TRUE);
776   overloadCountDict.setAutoDelete(TRUE);
777   MemberListIterator mli(*this);
778   MemberDef *md;
779   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
780   {
781     if (md->isDetailedSectionLinkable())
782     {
783       uint *pCount = overloadTotalDict.find(md->name());
784       if (pCount)
785       {
786         (*pCount)++;
787       }
788       else
789       {
790         overloadTotalDict.insert(md->name(),new uint(1));
791         overloadCountDict.insert(md->name(),new uint(1));
792       }
793     }
794   }
795
796   for ( mli.toFirst() ; (md=mli.current()) ; ++mli)
797   {
798     if (md->isDetailedSectionLinkable())
799     {
800       uint overloadCount = *overloadTotalDict.find(md->name());
801       uint *pCount = overloadCountDict.find(md->name());
802       QCString diskName=md->getOutputFileBase();
803       QCString title=md->qualifiedName();
804       startFile(ol,diskName,md->name(),title,HLI_None,!generateTreeView,diskName);
805       if (!generateTreeView)
806       {
807         container->writeNavigationPath(ol);
808         ol.endQuickIndices();
809       }
810       ol.startContents();
811
812       if (generateTreeView)
813       {
814         md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup);
815         (*pCount)++;
816         ol.endContents();
817         endFileWithNavPath(container,ol);
818       }
819       else
820       {
821         ol.writeString("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n"
822             "  <tr>\n"
823             "   <td valign=\"top\">\n");
824
825         container->writeQuickMemberLinks(ol,md);
826
827         ol.writeString("   </td>\n");
828         ol.writeString("   <td valign=\"top\" class=\"mempage\">\n");
829
830         md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup);
831         (*pCount)++;
832
833         ol.writeString("    </td>\n");
834         ol.writeString("  </tr>\n");
835         ol.writeString("</table>\n");
836
837         endFile(ol);
838       }
839     }
840   }
841   if (memberGroupList)
842   {
843     //printf("MemberList::writeDocumentation()  --  member groups\n");
844     MemberGroupListIterator mgli(*memberGroupList);
845     MemberGroup *mg;
846     for (;(mg=mgli.current());++mgli)
847     {
848       mg->writeDocumentationPage(ol,scopeName,container);
849     }
850   }
851 }
852
853 void MemberList::addMemberGroup(MemberGroup *mg)
854 {
855   if (memberGroupList==0)
856   {
857     memberGroupList=new MemberGroupList;
858   }
859   //printf("addMemberGroup: this=%p mg=%p\n",this,mg);
860   memberGroupList->append(mg);
861 }
862
863 void MemberList::addListReferences(Definition *def)
864 {
865   MemberListIterator mli(*this);
866   MemberDef *md;
867   for ( ; (md=mli.current()) ; ++mli)
868   {
869     if (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)
870     {
871       md->addListReference(def);
872       MemberList *enumFields = md->enumFieldList();
873       if (md->memberType()==MemberType_Enumeration && enumFields)
874       {
875         //printf("  Adding enum values!\n");
876         MemberListIterator vmli(*enumFields);
877         MemberDef *vmd;
878         for ( ; (vmd=vmli.current()) ; ++vmli)
879         {
880           //printf("   adding %s\n",vmd->name().data());  
881           vmd->addListReference(def);
882         }
883       }
884     }
885   }
886   if (memberGroupList)
887   {
888     MemberGroupListIterator mgli(*memberGroupList);
889     MemberGroup *mg;
890     for (;(mg=mgli.current());++mgli)
891     {
892       mg->addListReferences(def);
893     }
894   }
895 }
896
897 void MemberList::findSectionsInDocumentation()
898 {
899   MemberListIterator mli(*this);
900   MemberDef *md;
901   for ( ; (md=mli.current()) ; ++mli)
902   {
903     md->findSectionsInDocumentation();
904   }
905   if (memberGroupList)
906   {
907     MemberGroupListIterator mgli(*memberGroupList);
908     MemberGroup *mg;
909     for (;(mg=mgli.current());++mgli)
910     {
911       mg->findSectionsInDocumentation();
912     }
913   }
914 }
915
916 void MemberList::marshal(StorageIntf *s)
917 {
918   marshalInt(s,(int)m_listType);
919   marshalInt(s,m_varCnt);
920   marshalInt(s,m_funcCnt);
921   marshalInt(s,m_enumCnt);
922   marshalInt(s,m_enumValCnt);
923   marshalInt(s,m_typeCnt);
924   marshalInt(s,m_protoCnt);
925   marshalInt(s,m_defCnt);
926   marshalInt(s,m_friendCnt); 
927   marshalInt(s,m_numDecMembers);
928   marshalInt(s,m_numDocMembers);
929   marshalBool(s,m_inGroup);
930   marshalBool(s,m_inFile);
931   marshalBool(s,m_needsSorting);
932   if (memberGroupList==0)
933   {
934     marshalUInt(s,NULL_LIST); // null pointer representation
935   }
936   else
937   {
938     marshalUInt(s,memberGroupList->count());
939     QListIterator<MemberGroup> mgi(*memberGroupList);
940     MemberGroup *mg=0;
941     for (mgi.toFirst();(mg=mgi.current());++mgi)
942     {
943       mg->marshal(s);
944     }
945   }
946 }
947
948 void MemberList::unmarshal(StorageIntf *s)
949 {
950   m_listType       = (MemberListType)unmarshalInt(s);
951   m_varCnt         = unmarshalInt(s);
952   m_funcCnt        = unmarshalInt(s);
953   m_enumCnt        = unmarshalInt(s);
954   m_enumValCnt     = unmarshalInt(s);
955   m_typeCnt        = unmarshalInt(s);
956   m_protoCnt       = unmarshalInt(s);
957   m_defCnt         = unmarshalInt(s);
958   m_friendCnt      = unmarshalInt(s); 
959   m_numDecMembers  = unmarshalInt(s);
960   m_numDocMembers  = unmarshalInt(s);
961   m_inGroup        = unmarshalBool(s);
962   m_inFile         = unmarshalBool(s);
963   m_needsSorting   = unmarshalBool(s);
964   uint i,count     = unmarshalUInt(s); 
965   if (count==NULL_LIST) // empty list
966   {
967     memberGroupList = 0;
968   }
969   else // add member groups
970   {
971     memberGroupList = new MemberGroupList;
972     for (i=0;i<count;i++)
973     {
974       MemberGroup *mg = new MemberGroup;
975       mg->unmarshal(s);
976       memberGroupList->append(mg);
977     }
978   }
979 }
980
981 void MemberList::setNeedsSorting(bool b)
982 {
983   m_needsSorting = b;
984 }
985
986 QCString MemberList::listTypeAsString(MemberListType type) 
987 {
988   switch(type)
989   {
990     case MemberListType_pubMethods: return "pub-methods";
991     case MemberListType_proMethods: return "pro-methods";
992     case MemberListType_pacMethods: return "pac-methods";
993     case MemberListType_priMethods: return "pri-methods";
994     case MemberListType_pubStaticMethods: return "pub-static-methods";
995     case MemberListType_proStaticMethods: return "pro-static-methods";
996     case MemberListType_pacStaticMethods: return "pac-static-methods";
997     case MemberListType_priStaticMethods: return "pri-static-methods";
998     case MemberListType_pubSlots: return "pub-slots";
999     case MemberListType_proSlots: return "pro-slots";
1000     case MemberListType_priSlots: return "pri-slots";
1001     case MemberListType_pubAttribs: return "pub-attribs";
1002     case MemberListType_proAttribs: return "pro-attribs";
1003     case MemberListType_pacAttribs: return "pac-attribs";
1004     case MemberListType_priAttribs: return "pri-attribs";
1005     case MemberListType_pubStaticAttribs: return "pub-static-attribs";
1006     case MemberListType_proStaticAttribs: return "pro-static-attribs";
1007     case MemberListType_pacStaticAttribs: return "pac-static-attribs";
1008     case MemberListType_priStaticAttribs: return "pri-static-attribs";
1009     case MemberListType_pubTypes: return "pub-types";
1010     case MemberListType_proTypes: return "pro-types";
1011     case MemberListType_pacTypes: return "pac-types";
1012     case MemberListType_priTypes: return "pri-types";
1013     case MemberListType_related: return "related";
1014     case MemberListType_signals: return "signals";
1015     case MemberListType_friends: return "friends";
1016     case MemberListType_dcopMethods: return "dcop-methods";
1017     case MemberListType_properties: return "properties";
1018     case MemberListType_events: return "events";
1019     case MemberListType_interfaces: return "interfaces";
1020     case MemberListType_services: return "services";
1021     case MemberListType_decDefineMembers: return "define-members";
1022     case MemberListType_decProtoMembers: return "proto-members";
1023     case MemberListType_decTypedefMembers: return "typedef-members";
1024     case MemberListType_decEnumMembers: return "enum-members";
1025     case MemberListType_decFuncMembers: return "func-members";
1026     case MemberListType_decVarMembers: return "var-members";
1027     case MemberListType_decEnumValMembers: return "enumval-members";
1028     case MemberListType_decPubSlotMembers: return "pub-slot-members";
1029     case MemberListType_decProSlotMembers: return "pro-slot-members";
1030     case MemberListType_decPriSlotMembers: return "pri-slot-members";
1031     case MemberListType_decSignalMembers: return "signal-members";
1032     case MemberListType_decEventMembers: return "event-members";
1033     case MemberListType_decFriendMembers: return "friend-members";
1034     case MemberListType_decPropMembers: return "prop-members";
1035     case MemberListType_enumFields: return "enum-fields";
1036     case MemberListType_memberGroup: return "member-group";
1037     default: break;
1038   }
1039   return "";
1040 }
1041
1042 void MemberList::writeTagFile(FTextStream &tagFile)
1043 {
1044   MemberListIterator mli(*this);
1045   MemberDef *md;
1046   for ( ; (md=mli.current()) ; ++mli)
1047   {
1048     if (md->getLanguage()!=SrcLangExt_VHDL)
1049     {
1050       md->writeTagFile(tagFile);
1051       if (md->memberType()==MemberType_Enumeration && md->enumFieldList() && !md->isStrong())
1052       {
1053         MemberListIterator vmli(*md->enumFieldList());
1054         MemberDef *vmd;
1055         for ( ; (vmd=vmli.current()) ; ++vmli)
1056         {
1057           vmd->writeTagFile(tagFile);
1058         }
1059       }
1060     }
1061     else
1062     {
1063       VhdlDocGen::writeTagFile(md,tagFile);
1064     }
1065   }
1066   if (memberGroupList)
1067   {
1068     MemberGroupListIterator mgli(*memberGroupList);
1069     MemberGroup *mg;
1070     for (;(mg=mgli.current());++mgli)
1071     {
1072       mg->writeTagFile(tagFile);
1073     }
1074   }
1075 }
1076
1077 //--------------------------------------------------------------------------
1078
1079 int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const
1080 {
1081   //printf("MemberSDict::compareValues(%s,%s)\n",c1->name().data(),c2->name().data());
1082   int cmp = qstricmp(c1->name(),c2->name());
1083   if (cmp)
1084   {
1085     return cmp;
1086   }
1087   else
1088   {
1089     return c1->getDefLine()-c2->getDefLine();
1090   }
1091 }
1092
1093