Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / src / index.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2014 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 /** @file
19  *  @brief This file contains functions for the various index pages.
20  */
21
22 #include <stdlib.h>
23
24 #include <qtextstream.h>
25 #include <qdatetime.h>
26 #include <qdir.h>
27 #include <qregexp.h>
28
29 #include "message.h"
30 #include "index.h"
31 #include "doxygen.h"
32 #include "config.h"
33 #include "filedef.h"
34 #include "outputlist.h"
35 #include "util.h"
36 #include "groupdef.h"
37 #include "language.h"
38 #include "htmlgen.h"
39 #include "htmlhelp.h"
40 #include "ftvhelp.h"
41 #include "dot.h"
42 #include "pagedef.h"
43 #include "dirdef.h"
44 #include "vhdldocgen.h"
45 #include "layout.h"
46 #include "memberlist.h"
47 #include "classlist.h"
48 #include "namespacedef.h"
49 #include "filename.h"
50
51 #define MAX_ITEMS_BEFORE_MULTIPAGE_INDEX 200
52 #define MAX_ITEMS_BEFORE_QUICK_INDEX 30
53
54
55 int annotatedClasses;
56 int annotatedClassesPrinted;
57 int hierarchyClasses;
58 int documentedFiles;
59 int documentedGroups;
60 int documentedNamespaces;
61 int indexedPages;
62 int documentedClassMembers[CMHL_Total];
63 int documentedFileMembers[FMHL_Total];
64 int documentedNamespaceMembers[NMHL_Total];
65 int documentedHtmlFiles;
66 int documentedPages;
67 int documentedDirs;
68
69 static int countClassHierarchy();
70 static void countFiles(int &htmlFiles,int &files);
71 static int countGroups();
72 static int countDirs();
73 static int countNamespaces();
74 static int countAnnotatedClasses(int *cp);
75 static void countRelatedPages(int &docPages,int &indexPages);
76
77 void countDataStructures()
78 {
79   annotatedClasses           = countAnnotatedClasses(&annotatedClassesPrinted); // "classes" + "annotated"
80   hierarchyClasses           = countClassHierarchy();   // "hierarchy"
81   countFiles(documentedHtmlFiles,documentedFiles);      // "files"
82   countRelatedPages(documentedPages,indexedPages);      // "pages"
83   documentedGroups           = countGroups();           // "modules"
84   documentedNamespaces       = countNamespaces();       // "namespaces"
85   documentedDirs             = countDirs();             // "dirs"
86   // "globals"
87   // "namespacemembers"
88   // "functions"
89 }
90
91 static void startIndexHierarchy(OutputList &ol,int level)
92 {
93   ol.pushGeneratorState();
94   ol.disable(OutputGenerator::Man);
95   ol.disable(OutputGenerator::Html);
96   if (level<6) ol.startIndexList();
97   ol.enableAll();
98   ol.disable(OutputGenerator::Latex);
99   ol.disable(OutputGenerator::RTF);
100   ol.startItemList();
101   ol.popGeneratorState();
102 }
103
104 static void endIndexHierarchy(OutputList &ol,int level)
105 {
106   ol.pushGeneratorState();
107   ol.disable(OutputGenerator::Man);
108   ol.disable(OutputGenerator::Html);
109   if (level<6) ol.endIndexList();
110   ol.enableAll();
111   ol.disable(OutputGenerator::Latex);
112   ol.disable(OutputGenerator::RTF);
113   ol.endItemList();
114   ol.popGeneratorState();
115 }
116
117 //----------------------------------------------------------------------------
118
119 class MemberIndexList : public QList<MemberDef>
120 {
121   public:
122     typedef MemberDef ElementType;
123     MemberIndexList(uint letter) : QList<MemberDef>(), m_letter(letter) {}
124     ~MemberIndexList() {}
125     int compareValues(const MemberDef *md1, const MemberDef *md2) const
126     {
127       int result = qstricmp(md1->name(),md2->name());
128       if (result==0)
129       {
130         result = qstricmp(md1->qualifiedName(),md2->qualifiedName());
131       }
132       return result;
133     }
134     uint letter() const { return m_letter; }
135   private:
136     uint m_letter;
137 };
138
139 static LetterToIndexMap<MemberIndexList> g_memberIndexLetterUsed[CMHL_Total];
140 static LetterToIndexMap<MemberIndexList> g_fileIndexLetterUsed[FMHL_Total];
141 static LetterToIndexMap<MemberIndexList> g_namespaceIndexLetterUsed[NMHL_Total];
142
143 const int maxItemsBeforeQuickIndex = MAX_ITEMS_BEFORE_QUICK_INDEX;
144
145 //----------------------------------------------------------------------------
146
147 //----------------------------------------------------------------------------
148
149 static void startQuickIndexList(OutputList &ol,bool letterTabs=FALSE)
150 {
151   bool fancyTabs = TRUE;
152   if (fancyTabs)
153   {
154     if (letterTabs)
155     {
156       ol.writeString("  <div id=\"navrow4\" class=\"tabs3\">\n"); 
157     }
158     else
159     {
160       ol.writeString("  <div id=\"navrow3\" class=\"tabs2\">\n"); 
161     }
162     ol.writeString("    <ul class=\"tablist\">\n"); 
163   }
164   else
165   {
166     ol.writeString("  <div class=\"qindex\">"); 
167   }
168 }
169
170 static void endQuickIndexList(OutputList &ol)
171 {
172   bool fancyTabs = TRUE;
173   if (fancyTabs)
174   {
175     ol.writeString("    </ul>\n");
176   }
177   ol.writeString("  </div>\n");
178 }
179
180 static void startQuickIndexItem(OutputList &ol,const char *l,
181                                 bool hl,bool compact,bool &first)
182 {
183   bool fancyTabs = TRUE;
184   if (!first && compact && !fancyTabs) ol.writeString(" | ");
185   first=FALSE;
186   if (fancyTabs)
187   {
188     ol.writeString("      <li"); 
189     if (hl) ol.writeString(" class=\"current\"");
190     ol.writeString("><a ");
191   }
192   else
193   {
194     if (!compact) ol.writeString("<li>");
195     if (hl && compact)
196     {
197       ol.writeString("<a class=\"qindexHL\" ");
198     }
199     else
200     {
201       ol.writeString("<a class=\"qindex\" ");
202     }
203   }
204   ol.writeString("href=\""); 
205   ol.writeString(l);
206   ol.writeString("\">");
207   if (fancyTabs)
208   {
209     ol.writeString("<span>");
210   }
211 }
212
213 static void endQuickIndexItem(OutputList &ol)
214 {
215   bool fancyTabs=TRUE;
216   if (fancyTabs) ol.writeString("</span>");
217   ol.writeString("</a>");
218   if (fancyTabs) ol.writeString("</li>\n");
219 }
220
221 // don't make this static as it is called from a template function and some
222 // old compilers don't support calls to static functions from a template.
223 QCString fixSpaces(const QCString &s)
224 {
225   return substitute(s," ","&#160;");
226 }
227
228 void startTitle(OutputList &ol,const char *fileName,Definition *def)
229 {
230   ol.startHeaderSection();
231   if (def) def->writeSummaryLinks(ol);
232   ol.startTitleHead(fileName);
233   ol.pushGeneratorState();
234   ol.disable(OutputGenerator::Man);
235 }
236
237 void endTitle(OutputList &ol,const char *fileName,const char *name)
238 {
239   ol.popGeneratorState();
240   ol.endTitleHead(fileName,name);
241   ol.endHeaderSection();
242 }
243
244 void startFile(OutputList &ol,const char *name,const char *manName,
245                const char *title,HighlightedItem hli,bool additionalIndices,
246                const char *altSidebarName)
247 {
248   static bool disableIndex     = Config_getBool("DISABLE_INDEX");
249   ol.startFile(name,manName,title);
250   ol.startQuickIndices();
251   if (!disableIndex)
252   {
253     ol.writeQuickLinks(TRUE,hli,name);
254   }
255   if (!additionalIndices)
256   {
257     ol.endQuickIndices();
258   }
259   ol.writeSplitBar(altSidebarName ? altSidebarName : name);
260   ol.writeSearchInfo();
261 }
262
263 void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents,
264              const QCString &navPath)
265 {
266   static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
267   ol.pushGeneratorState();
268   ol.disableAllBut(OutputGenerator::Html);
269   if (!skipNavIndex)
270   {
271     if (!skipEndContents) ol.endContents();
272     if (generateTreeView)
273     {
274       ol.writeString("</div><!-- doc-content -->\n");
275     }
276   }
277   ol.writeFooter(navPath); // write the footer
278   ol.popGeneratorState();
279   ol.endFile();
280 }
281
282 void endFileWithNavPath(Definition *d,OutputList &ol)
283 {
284   static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
285   QCString navPath;
286   if (generateTreeView)
287   {
288     ol.pushGeneratorState();
289     ol.disableAllBut(OutputGenerator::Html);
290     ol.writeString("</div><!-- doc-content -->\n");
291     ol.popGeneratorState();
292     navPath = d->navigationPathAsString();
293   }
294   endFile(ol,generateTreeView,TRUE,navPath);
295 }
296
297 //----------------------------------------------------------------------
298 template<class T> 
299 void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
300                        const QCString &name,const QCString &anchor,
301                        bool addToIndex=TRUE,bool preventSeparateIndex=FALSE)
302 {
303   bool hasMembers = def->getMemberLists().count()>0 || def->getMemberGroupSDict()!=0;
304   Doxygen::indexList->addContentsItem(hasMembers,name,
305                                      def->getReference(),def->getOutputFileBase(),anchor,
306                                      hasMembers && !preventSeparateIndex,
307                                      addToIndex,
308                                      def);
309   int numClasses=0;
310   ClassSDict *classes = def->getClassSDict();
311   if (classes)
312   {
313      ClassDef *cd;
314      ClassSDict::Iterator it(*classes);
315      for (;(cd=it.current());++it)
316      {
317        if (cd->isLinkable()) numClasses++;
318      }
319   }
320   //printf("addMembersToIndex(def=%s hasMembers=%d numClasses=%d)\n",def->name().data(),hasMembers,numClasses);
321   if (hasMembers || numClasses>0)
322   {
323     Doxygen::indexList->incContentsDepth();
324     QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(part));
325     LayoutDocEntry *lde;
326     for (eli.toFirst();(lde=eli.current());++eli)
327     {
328       if (lde->kind()==LayoutDocEntry::MemberDef)
329       {
330         LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
331         MemberList *ml = def->getMemberList(lmd->type);
332         if (ml)
333         {
334           MemberListIterator mi(*ml);
335           MemberDef *md;
336           for (mi.toFirst();(md=mi.current());++mi)
337           {
338             MemberList *enumList = md->enumFieldList();
339             bool isDir = enumList!=0 && md->isEnumerate();
340             bool isAnonymous = md->name().find('@')!=-1;
341             static bool hideUndocMembers = Config_getBool("HIDE_UNDOC_MEMBERS");
342             static bool extractStatic = Config_getBool("EXTRACT_STATIC");
343             if (!isAnonymous && 
344                 (!hideUndocMembers || md->hasDocumentation()) &&
345                 (!md->isStatic() || extractStatic)
346                )
347             {
348               if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope)
349               {
350                 Doxygen::indexList->addContentsItem(isDir,
351                   md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex);
352               }
353               else // inherited member
354               {
355                 Doxygen::indexList->addContentsItem(isDir,
356                   md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex);
357               }
358             }
359             if (isDir)
360             {
361               if (!isAnonymous)
362               {
363                 Doxygen::indexList->incContentsDepth();
364               }
365               MemberListIterator emli(*enumList);
366               MemberDef *emd;
367               for (emli.toFirst();(emd=emli.current());++emli)
368               {
369                 if (!hideUndocMembers || emd->hasDocumentation())
370                 {
371                   if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope)
372                   {
373                     Doxygen::indexList->addContentsItem(FALSE,
374                         emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex);
375                   }
376                   else // inherited member
377                   {
378                     Doxygen::indexList->addContentsItem(FALSE,
379                         emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex);
380                   }
381                 }
382               }
383               if (!isAnonymous)
384               {
385                 Doxygen::indexList->decContentsDepth();
386               }
387             }
388           }
389         }
390       }
391       else if (lde->kind()==LayoutDocEntry::NamespaceClasses || 
392                lde->kind()==LayoutDocEntry::FileClasses || 
393                lde->kind()==LayoutDocEntry::ClassNestedClasses
394               )
395       {
396         if (classes)
397         {
398           ClassDef *cd;
399           ClassSDict::Iterator it(*classes);
400           for (;(cd=it.current());++it)
401           {
402             if (cd->isLinkable() && (cd->partOfGroups()==0 || def->definitionType()==Definition::TypeGroup))
403             {
404               static bool inlineSimpleStructs = Config_getBool("INLINE_SIMPLE_STRUCTS");
405               bool isNestedClass = def->definitionType()==Definition::TypeClass;
406               addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(),
407                                 addToIndex && (isNestedClass || (cd->isSimple() && inlineSimpleStructs)),
408                                 preventSeparateIndex || cd->isEmbeddedInOuterScope());
409             }
410           }
411         }
412       }
413     }
414
415     Doxygen::indexList->decContentsDepth();
416   }
417 }
418
419
420 //----------------------------------------------------------------------------
421 /*! Generates HTML Help tree of classes */
422
423 static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSuper,int level,FTVHelp* ftv,bool addToIndex)
424 {
425   if (bcl==0) return;
426   BaseClassListIterator bcli(*bcl);
427   bool started=FALSE;
428   for ( ; bcli.current() ; ++bcli)
429   {
430     ClassDef *cd=bcli.current()->classDef;
431     if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
432     {
433       continue;
434     }
435
436     bool b;
437     if (cd->getLanguage()==SrcLangExt_VHDL)
438     {
439       b=hasVisibleRoot(cd->subClasses());
440     }
441     else
442     {
443       b=hasVisibleRoot(cd->baseClasses());
444     }
445
446     if (cd->isVisibleInHierarchy() && b) // hasVisibleRoot(cd->baseClasses()))
447     {
448       if (!started)
449       {
450         startIndexHierarchy(ol,level);
451         if (addToIndex)
452         {
453           Doxygen::indexList->incContentsDepth();
454         }
455         if (ftv)
456         {
457           ftv->incContentsDepth();
458         }
459         started=TRUE;
460       }
461       ol.startIndexListItem();
462       //printf("Passed...\n");
463       bool hasChildren = !cd->visited && !hideSuper && classHasVisibleChildren(cd);
464       //printf("tree4: Has children %s: %d\n",cd->name().data(),hasChildren);
465       if (cd->isLinkable())
466       {
467         //printf("Writing class %s\n",cd->displayName().data());
468         ol.startIndexItem(cd->getReference(),cd->getOutputFileBase());
469         ol.parseText(cd->displayName());
470         ol.endIndexItem(cd->getReference(),cd->getOutputFileBase());
471         if (cd->isReference()) 
472         { 
473           ol.startTypewriter(); 
474           ol.docify(" [external]");
475           ol.endTypewriter();
476         }
477         if (addToIndex)
478         {
479           Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor());
480         }
481         if (ftv)
482         {
483           if (cd->getLanguage()==SrcLangExt_VHDL)
484           {
485             ftv->addContentsItem(hasChildren,bcli.current()->usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd);
486           }
487           else
488           {
489             ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd);
490           }
491         }
492       }
493       else
494       {
495         ol.startIndexItem(0,0);
496         ol.parseText(cd->name());
497         ol.endIndexItem(0,0);
498         if (addToIndex)
499         {
500           Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),0,0,0);
501         }
502         if (ftv)
503         {
504           ftv->addContentsItem(hasChildren,cd->displayName(),0,0,0,FALSE,FALSE,cd);
505         }
506       }
507       if (hasChildren)
508       {
509         //printf("Class %s at %p visited=%d\n",cd->name().data(),cd,cd->visited);
510         bool wasVisited=cd->visited;
511         cd->visited=TRUE;
512         if (cd->getLanguage()==SrcLangExt_VHDL) 
513         {
514           writeClassTree(ol,cd->baseClasses(),wasVisited,level+1,ftv,addToIndex);
515         }
516         else       
517         {
518           writeClassTree(ol,cd->subClasses(),wasVisited,level+1,ftv,addToIndex);
519         }
520       }
521       ol.endIndexListItem();
522     }
523   }
524   if (started) 
525   {
526     endIndexHierarchy(ol,level);
527     if (addToIndex)
528     {
529       Doxygen::indexList->decContentsDepth();
530     }
531     if (ftv)
532     {
533       ftv->decContentsDepth();
534     }
535   }
536 }
537
538 //----------------------------------------------------------------------------
539
540 static bool dirHasVisibleChildren(DirDef *dd)
541 {
542   if (dd->hasDocumentation()) return TRUE;
543
544   QListIterator<FileDef> fli(*dd->getFiles());
545   FileDef *fd;
546   for (fli.toFirst();(fd=fli.current());++fli)
547   {
548     bool genSourceFile;
549     if (fileVisibleInIndex(fd,genSourceFile))
550     {
551       return TRUE;
552     }
553     if (genSourceFile)
554     {
555       return TRUE;
556     }
557   }
558
559   QListIterator<DirDef> dli(dd->subDirs());
560   DirDef *subdd;
561   for (dli.toFirst();(subdd=dli.current());++dli)
562   {
563     if (dirHasVisibleChildren(subdd))
564     {
565       return TRUE;
566     }
567   }
568   return FALSE;
569 }
570
571 //----------------------------------------------------------------------------
572 static void writeDirTreeNode(OutputList &ol, DirDef *dd, int level, FTVHelp* ftv,bool addToIndex)
573 {
574   if (level>20)
575   {
576     warn(dd->getDefFileName(),dd->getDefLine(),
577         "maximum nesting level exceeded for directory %s: "
578         "check for possible recursive directory relation!\n",dd->name().data()
579         );
580     return;
581   }
582
583   if (!dirHasVisibleChildren(dd))
584   {
585     return;
586   }
587
588   static bool tocExpand = TRUE; //Config_getBool("TOC_EXPAND");
589   bool isDir = dd->subDirs().count()>0 || // there are subdirs
590                (tocExpand &&              // or toc expand and
591                 dd->getFiles() && dd->getFiles()->count()>0 // there are files
592                );
593   //printf("gd=`%s': pageDict=%d\n",gd->name().data(),gd->pageDict->count());
594   if (addToIndex)
595   {
596     Doxygen::indexList->addContentsItem(isDir,dd->shortName(),dd->getReference(),dd->getOutputFileBase(),0,TRUE,TRUE); 
597     Doxygen::indexList->incContentsDepth();
598   }
599   if (ftv)
600   {
601     ftv->addContentsItem(isDir,dd->shortName(),dd->getReference(),
602                          dd->getOutputFileBase(),0,FALSE,TRUE,dd); 
603     ftv->incContentsDepth();
604   }
605
606   ol.startIndexListItem();
607   ol.startIndexItem(dd->getReference(),dd->getOutputFileBase());
608   ol.parseText(dd->shortName());
609   ol.endIndexItem(dd->getReference(),dd->getOutputFileBase());
610   if (dd->isReference()) 
611   { 
612     ol.startTypewriter(); 
613     ol.docify(" [external]");
614     ol.endTypewriter();
615   }
616
617   // write sub directories
618   if (dd->subDirs().count()>0)
619   {
620     startIndexHierarchy(ol,level+1);
621     QListIterator<DirDef> dli(dd->subDirs());
622     DirDef *subdd = 0;
623     for (dli.toFirst();(subdd=dli.current());++dli)
624     {
625       writeDirTreeNode(ol,subdd,level+1,ftv,addToIndex);
626     }
627     endIndexHierarchy(ol,level+1); 
628   }
629
630   FileList *fileList=dd->getFiles();
631   int fileCount=0;
632   if (fileList && fileList->count()>0)
633   {
634     QListIterator<FileDef> it(*fileList);
635     FileDef *fd;
636     for (;(fd=it.current());++it)
637     {
638       //static bool allExternals = Config_getBool("ALLEXTERNALS");
639       //if ((allExternals && fd->isLinkable()) || fd->isLinkableInProject())
640       //{
641       //  fileCount++;
642       //}
643       bool genSourceFile;
644       if (fileVisibleInIndex(fd,genSourceFile))
645       {
646         fileCount++;
647       }
648       else if (genSourceFile)
649       {
650         fileCount++;
651       }
652     }
653     if (fileCount>0)
654     {
655       startIndexHierarchy(ol,level+1);
656       for (it.toFirst();(fd=it.current());++it)
657       {
658         bool doc,src;
659         doc = fileVisibleInIndex(fd,src);
660         QCString reference;
661         QCString outputBase;
662         if (doc) 
663         {
664           reference  = fd->getReference();
665           outputBase = fd->getOutputFileBase();
666         }
667         if (doc || src)
668         {
669           ol.startIndexListItem();
670           ol.startIndexItem(reference,outputBase);
671           ol.parseText(fd->displayName());
672           ol.endIndexItem(reference,outputBase);
673           ol.endIndexListItem();
674           if (ftv && (src || doc))
675           {
676             ftv->addContentsItem(FALSE,
677                 fd->displayName(),
678                 reference,outputBase,
679                 0,FALSE,FALSE,fd); 
680           }
681         }
682       }
683       endIndexHierarchy(ol,level+1); 
684     }
685   }
686
687   if (tocExpand && addToIndex)
688   {
689     // write files of this directory
690     if (fileCount>0)
691     {
692       QListIterator<FileDef> it(*fileList);
693       FileDef *fd;
694       for (;(fd=it.current());++it)
695       {
696         //static bool allExternals = Config_getBool("ALLEXTERNALS");
697         //if ((allExternals && fd->isLinkable()) || fd->isLinkableInProject())
698         bool doc,src;
699         doc = fileVisibleInIndex(fd,src);
700         if (doc)
701         {
702           addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),TRUE);
703         }
704         else if (src)
705         {
706           Doxygen::indexList->addContentsItem(
707                FALSE, convertToHtml(fd->name(),TRUE), 0, 
708                fd->getSourceFileBase(), 0, FALSE, TRUE, fd);
709         }
710       }
711     }
712   }
713   ol.endIndexListItem();
714
715   if (addToIndex)
716   {
717     Doxygen::indexList->decContentsDepth();
718   }
719   if (ftv)
720   {
721     ftv->decContentsDepth();
722   }
723 }
724
725 static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
726 {
727   if (ftv)
728   {
729     ol.pushGeneratorState(); 
730     ol.disable(OutputGenerator::Html);
731   }
732   static bool fullPathNames = Config_getBool("FULL_PATH_NAMES");
733   startIndexHierarchy(ol,0);
734   if (fullPathNames)
735   {
736     SDict<DirDef>::Iterator dli(*Doxygen::directories);
737     DirDef *dd;
738     for (dli.toFirst();(dd=dli.current());++dli)
739     {
740       if (dd->getOuterScope()==Doxygen::globalScope) 
741       {
742         writeDirTreeNode(ol,dd,0,ftv,addToIndex);
743       }
744     }
745   }
746   if (ftv)
747   {
748     FileNameListIterator fnli(*Doxygen::inputNameList); 
749     FileName *fn;
750     for (fnli.toFirst();(fn=fnli.current());++fnli)
751     {
752       FileNameIterator fni(*fn);
753       FileDef *fd;
754       for (;(fd=fni.current());++fni)
755       {
756         static bool fullPathNames = Config_getBool("FULL_PATH_NAMES");
757         if (!fullPathNames || fd->getDirDef()==0) // top level file
758         {
759           bool doc,src;
760           doc = fileVisibleInIndex(fd,src);
761           QCString reference, outputBase;
762           if (doc)
763           {
764             reference = fd->getReference();
765             outputBase = fd->getOutputFileBase();
766           }
767           if (doc || src)
768           {
769             ftv->addContentsItem(FALSE,fd->displayName(),          
770                                  reference, outputBase, 0,         
771                                  FALSE,FALSE,fd);
772           }
773           if (addToIndex)
774           {
775             if (doc)
776             {
777               addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),TRUE);
778             }
779             else if (src)
780             {
781               Doxygen::indexList->addContentsItem(
782                   FALSE, convertToHtml(fd->name(),TRUE), 0, 
783                   fd->getSourceFileBase(), 0, FALSE, TRUE, fd);
784             }
785           }
786         }
787       }
788     }
789   }
790   endIndexHierarchy(ol,0); 
791   if (ftv)
792   {
793     ol.popGeneratorState(); 
794   }
795 }
796
797
798 //----------------------------------------------------------------------------
799
800 static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FTVHelp* ftv,bool addToIndex)
801 {
802   ClassSDict::Iterator cli(*cl);
803   for (;cli.current(); ++cli)
804   {
805     ClassDef *cd=cli.current();
806     //printf("class %s hasVisibleRoot=%d isVisibleInHierarchy=%d\n",
807     //             cd->name().data(),
808     //              hasVisibleRoot(cd->baseClasses()),
809     //              cd->isVisibleInHierarchy()
810     //      );
811     bool b;
812     if (cd->getLanguage()==SrcLangExt_VHDL)
813     {
814       if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
815       {
816         continue;
817       }
818       b=!hasVisibleRoot(cd->subClasses());
819     }
820     else
821     {
822       b=!hasVisibleRoot(cd->baseClasses());
823     }
824
825     if (b)  //filter on root classes
826     {
827       if (cd->isVisibleInHierarchy()) // should it be visible
828       {
829         if (!started)
830         {
831           startIndexHierarchy(ol,0);
832           if (addToIndex)
833           {
834             Doxygen::indexList->incContentsDepth();
835           }
836           started=TRUE;
837         }
838         ol.startIndexListItem();
839         bool hasChildren = !cd->visited && classHasVisibleChildren(cd); 
840         //printf("list: Has children %s: %d\n",cd->name().data(),hasChildren);
841         if (cd->isLinkable())
842         {
843           //printf("Writing class %s isLinkable()=%d isLinkableInProject()=%d cd->templateMaster()=%p\n",
844           //    cd->displayName().data(),cd->isLinkable(),cd->isLinkableInProject(),cd->templateMaster());
845           ol.startIndexItem(cd->getReference(),cd->getOutputFileBase());
846           ol.parseText(cd->displayName());
847           ol.endIndexItem(cd->getReference(),cd->getOutputFileBase());
848           if (cd->isReference()) 
849           {
850             ol.startTypewriter(); 
851             ol.docify(" [external]");
852             ol.endTypewriter();
853           }
854           if (addToIndex)
855           {
856             if (cd->getLanguage()!=SrcLangExt_VHDL) // prevents double insertion in Design Unit List
857                   Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE);
858           }
859           if (ftv)
860           {
861             ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); 
862           }
863         }
864         else
865         {
866           ol.startIndexItem(0,0);
867           ol.parseText(cd->displayName());
868           ol.endIndexItem(0,0);
869           if (addToIndex)
870           {
871             Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),0,0,0,FALSE,FALSE);
872           }
873           if (ftv)
874           {
875             ftv->addContentsItem(hasChildren,cd->displayName(),0,0,0,FALSE,FALSE,cd); 
876           }
877         }
878         if (cd->getLanguage()==SrcLangExt_VHDL && hasChildren) 
879         {
880           writeClassTree(ol,cd->baseClasses(),cd->visited,1,ftv,addToIndex);
881           cd->visited=TRUE;
882         }
883         else if (hasChildren)
884         {
885           writeClassTree(ol,cd->subClasses(),cd->visited,1,ftv,addToIndex);
886           cd->visited=TRUE;
887         }
888         ol.endIndexListItem();
889       }
890     }
891   }
892 }
893
894 static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
895 {
896   initClassHierarchy(Doxygen::classSDict);
897   initClassHierarchy(Doxygen::hiddenClasses);
898   if (ftv)
899   {
900     ol.pushGeneratorState(); 
901     ol.disable(OutputGenerator::Html);
902   }
903   bool started=FALSE;
904   writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex);
905   writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex);
906   if (started) 
907   {
908     endIndexHierarchy(ol,0);
909     if (addToIndex)
910     {
911       Doxygen::indexList->decContentsDepth();
912     }
913   }
914   if (ftv)
915   {
916     ol.popGeneratorState(); 
917   }
918 }
919
920 //----------------------------------------------------------------------------
921
922 static int countClassesInTreeList(const ClassSDict &cl)
923 {
924   int count=0;
925   ClassSDict::Iterator cli(cl);
926   for (;cli.current(); ++cli)
927   {
928     ClassDef *cd=cli.current();
929     if (!hasVisibleRoot(cd->baseClasses())) // filter on root classes
930     {
931       if (cd->isVisibleInHierarchy()) // should it be visible
932       {
933         if (cd->subClasses()) // should have sub classes
934         {
935           count++;
936         }
937       }
938     }
939   }
940   return count;
941 }
942
943 static int countClassHierarchy()
944 {
945   int count=0;
946   initClassHierarchy(Doxygen::classSDict);
947   initClassHierarchy(Doxygen::hiddenClasses);
948   count+=countClassesInTreeList(*Doxygen::classSDict);
949   count+=countClassesInTreeList(*Doxygen::hiddenClasses);
950   return count;
951 }
952
953 //----------------------------------------------------------------------------
954
955 static void writeHierarchicalIndex(OutputList &ol)
956 {
957   if (hierarchyClasses==0) return;
958   ol.pushGeneratorState();
959   //1.{
960   ol.disable(OutputGenerator::Man);
961
962   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy);
963   QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
964   bool addToIndex = lne==0 || lne->visible();
965
966   startFile(ol,"hierarchy",0, title, HLI_Hierarchy);
967   startTitle(ol,0);
968   ol.parseText(title);
969   endTitle(ol,0,0);
970   ol.startContents();
971   ol.startTextBlock();
972
973   if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY"))
974   {
975     ol.disable(OutputGenerator::Latex);
976     ol.disable(OutputGenerator::RTF);
977     ol.startParagraph();
978     ol.startTextLink("inherits",0);
979     ol.parseText(theTranslator->trGotoGraphicalHierarchy());
980     ol.endTextLink();
981     ol.endParagraph();
982     ol.enable(OutputGenerator::Latex);
983     ol.enable(OutputGenerator::RTF);
984   }
985   ol.parseText(lne ? lne->intro() : theTranslator->trClassHierarchyDescription());
986   ol.endTextBlock();
987
988   // ---------------
989   // Static class hierarchy for Latex/RTF
990   // ---------------
991   ol.pushGeneratorState();
992   //2.{
993   ol.disable(OutputGenerator::Html);
994   Doxygen::indexList->disable();
995
996   writeClassHierarchy(ol,0,addToIndex);
997
998   Doxygen::indexList->enable();
999   ol.popGeneratorState();
1000   //2.}
1001
1002   // ---------------
1003   // Dynamic class hierarchical index for HTML
1004   // ---------------
1005   ol.pushGeneratorState(); 
1006   //2.{
1007   ol.disableAllBut(OutputGenerator::Html);
1008
1009   {
1010     if (addToIndex)
1011     {
1012       Doxygen::indexList->addContentsItem(TRUE,title,0,"hierarchy",0,TRUE,TRUE); 
1013     }
1014     FTVHelp* ftv = new FTVHelp(FALSE);
1015     writeClassHierarchy(ol,ftv,addToIndex);
1016     QGString outStr;
1017     FTextStream t(&outStr);
1018     ftv->generateTreeViewInline(t);
1019     ol.pushGeneratorState(); 
1020     ol.disableAllBut(OutputGenerator::Html);
1021     ol.writeString(outStr);
1022     ol.popGeneratorState();
1023     delete ftv;
1024   }
1025   ol.popGeneratorState();
1026   //2.}
1027   // ------
1028
1029   endFile(ol);
1030   ol.popGeneratorState();
1031   //1.}
1032 }
1033
1034 //----------------------------------------------------------------------------
1035
1036 static void writeGraphicalClassHierarchy(OutputList &ol)
1037 {
1038   if (hierarchyClasses==0) return;
1039   ol.disableAllBut(OutputGenerator::Html);
1040   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy);
1041   QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
1042   startFile(ol,"inherits",0,title,HLI_Hierarchy,FALSE,"hierarchy");
1043   startTitle(ol,0);
1044   ol.parseText(title);
1045   endTitle(ol,0,0);
1046   ol.startContents();
1047   ol.startTextBlock();
1048   ol.startParagraph();
1049   ol.startTextLink("hierarchy",0);
1050   ol.parseText(theTranslator->trGotoTextualHierarchy());
1051   ol.endTextLink();
1052   ol.endParagraph();
1053   ol.endTextBlock();
1054   DotGfxHierarchyTable g;
1055   ol.writeGraphicalHierarchy(g);
1056   endFile(ol);
1057   ol.enableAll();
1058 }
1059
1060 //----------------------------------------------------------------------------
1061
1062 static void countFiles(int &htmlFiles,int &files)
1063 {
1064   htmlFiles=0;
1065   files=0;
1066   FileNameListIterator fnli(*Doxygen::inputNameList);
1067   FileName *fn;
1068   for (;(fn=fnli.current());++fnli)
1069   {
1070     FileNameIterator fni(*fn);
1071     FileDef *fd;
1072     for (;(fd=fni.current());++fni)
1073     {
1074       bool doc,src;
1075       doc = fileVisibleInIndex(fd,src);
1076       if (doc || src)
1077       {
1078         htmlFiles++;
1079       }
1080       if (doc)
1081       {
1082         files++;
1083       }
1084     }
1085   }
1086 }
1087
1088 static void writeSingleFileIndex(OutputList &ol,FileDef *fd)
1089 {
1090   //printf("Found filedef %s\n",fd->name().data());
1091   bool doc = fd->isLinkableInProject();
1092   bool src = fd->generateSourceFile();
1093   bool nameOk = !fd->isDocumentationFile();
1094   if (nameOk && (doc || src) && !fd->isReference())
1095   {
1096     QCString path;
1097     if (Config_getBool("FULL_PATH_NAMES"))
1098     {
1099       path=stripFromPath(fd->getPath().copy());
1100     }
1101     QCString fullName=fd->name();
1102     if (!path.isEmpty())
1103     {
1104       if (path.at(path.length()-1)!='/') fullName.prepend("/");
1105       fullName.prepend(path);
1106     }
1107
1108     ol.startIndexKey();
1109     ol.docify(path);
1110     if (doc)
1111     {
1112       ol.writeObjectLink(0,fd->getOutputFileBase(),0,fd->name());
1113       //if (addToIndex)
1114       //{
1115       //  addMembersToIndex(fd,LayoutDocManager::File,fullName,QCString());
1116       //}
1117     }
1118     else
1119     {
1120       ol.startBold();
1121       ol.docify(fd->name());
1122       ol.endBold();
1123       //if (addToIndex)
1124       //{
1125       //  Doxygen::indexList->addContentsItem(FALSE,fullName,0,0,0);
1126       //}
1127     }
1128     if (src)
1129     {
1130       ol.pushGeneratorState();
1131       ol.disableAllBut(OutputGenerator::Html);
1132       ol.docify(" ");
1133       ol.startTextLink(fd->includeName(),0);
1134       ol.docify("[");
1135       ol.parseText(theTranslator->trCode());
1136       ol.docify("]");
1137       ol.endTextLink();
1138       ol.popGeneratorState();
1139     }
1140     ol.endIndexKey();
1141     bool hasBrief = !fd->briefDescription().isEmpty();
1142     ol.startIndexValue(hasBrief);
1143     if (hasBrief)
1144     {
1145       //ol.docify(" (");
1146       ol.generateDoc(
1147           fd->briefFile(),fd->briefLine(),
1148           fd,0,
1149           fd->briefDescription(TRUE),
1150           FALSE, // index words
1151           FALSE, // isExample
1152           0,     // example name
1153           TRUE,  // single line
1154           TRUE   // link from index
1155           );
1156       //ol.docify(")");
1157     }
1158     ol.endIndexValue(fd->getOutputFileBase(),hasBrief);
1159     //ol.popGeneratorState();
1160     // --------------------------------------------------------
1161   }
1162 }
1163
1164 //----------------------------------------------------------------------------
1165
1166 static void writeFileIndex(OutputList &ol)
1167 {
1168   if (documentedHtmlFiles==0) return;
1169
1170   ol.pushGeneratorState();
1171   ol.disable(OutputGenerator::Man);
1172   if (documentedFiles==0) ol.disableAllBut(OutputGenerator::Html);
1173
1174   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileList);
1175   if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files); // fall back
1176   QCString title = lne ? lne->title() : theTranslator->trFileList();
1177   bool addToIndex = lne==0 || lne->visible();
1178
1179   startFile(ol,"files",0,title,HLI_Files);
1180   startTitle(ol,0);
1181   //if (!Config_getString("PROJECT_NAME").isEmpty()) 
1182   //{
1183   //  title.prepend(Config_getString("PROJECT_NAME")+" ");
1184   //}
1185   ol.parseText(title);
1186   endTitle(ol,0,0);
1187   ol.startContents();
1188   ol.startTextBlock();
1189
1190   if (addToIndex)
1191   {
1192     Doxygen::indexList->addContentsItem(TRUE,title,0,"files",0,TRUE,TRUE); 
1193     Doxygen::indexList->incContentsDepth();
1194   }
1195
1196   ol.parseText(lne ? lne->intro() : theTranslator->trFileListDescription(Config_getBool("EXTRACT_ALL")));
1197   ol.endTextBlock();
1198
1199   // ---------------
1200   // Flat file index
1201   // ---------------
1202
1203   // 1. {
1204   ol.pushGeneratorState();
1205   ol.disable(OutputGenerator::Html);
1206
1207   OutputNameDict outputNameDict(1009);
1208   OutputNameList outputNameList;
1209   outputNameList.setAutoDelete(TRUE);
1210
1211   if (Config_getBool("FULL_PATH_NAMES"))
1212   {
1213     // re-sort input files in (dir,file) output order instead of (file,dir) input order 
1214     FileNameListIterator fnli(*Doxygen::inputNameList);
1215     FileName *fn;
1216     for (fnli.toFirst();(fn=fnli.current());++fnli)
1217     {
1218       FileNameIterator fni(*fn);
1219       FileDef *fd;
1220       for (;(fd=fni.current());++fni)
1221       {
1222         QCString path=fd->getPath();
1223         if (path.isEmpty()) path="[external]";
1224         FileList *fl = outputNameDict.find(path);
1225         if (fl)
1226         {
1227           fl->append(fd);
1228           //printf("+ inserting %s---%s\n",fd->getPath().data(),fd->name().data());
1229         }
1230         else
1231         {
1232           //printf("o inserting %s---%s\n",fd->getPath().data(),fd->name().data());
1233           fl = new FileList(path);
1234           fl->append(fd);
1235           outputNameList.append(fl);
1236           outputNameDict.insert(path,fl);
1237         }
1238       }
1239     }
1240   }
1241
1242   ol.startIndexList();
1243   if (Config_getBool("FULL_PATH_NAMES"))
1244   {
1245     outputNameList.sort();
1246     QListIterator<FileList> fnli(outputNameList);
1247     FileList *fl;
1248     for (fnli.toFirst();(fl=fnli.current());++fnli)
1249     {
1250       fl->sort();
1251       QListIterator<FileDef> it(*fl);
1252       FileDef *fd;
1253       for (;(fd=it.current());++it)
1254       {
1255         writeSingleFileIndex(ol,fd);
1256       }
1257     }
1258   }
1259   else
1260   {
1261     FileNameListIterator fnli(*Doxygen::inputNameList);
1262     FileName *fn;
1263     for (fnli.toFirst();(fn=fnli.current());++fnli)
1264     {
1265       FileNameIterator fni(*fn);
1266       FileDef *fd;
1267       for (;(fd=fni.current());++fni)
1268       {
1269         writeSingleFileIndex(ol,fd);
1270       }
1271     }
1272   }
1273   ol.endIndexList();
1274
1275   // 1. }
1276   ol.popGeneratorState();
1277
1278   // ---------------
1279   // Hierarchical file index for HTML
1280   // ---------------
1281   ol.pushGeneratorState(); 
1282   ol.disableAllBut(OutputGenerator::Html);
1283
1284   FTVHelp* ftv = new FTVHelp(FALSE);
1285   writeDirHierarchy(ol,ftv,addToIndex);
1286   QGString outStr;
1287   FTextStream t(&outStr);
1288   ftv->generateTreeViewInline(t);
1289   ol.writeString(outStr);
1290   delete ftv;
1291
1292   ol.popGeneratorState();
1293   // ------
1294
1295   if (addToIndex)
1296   {
1297     Doxygen::indexList->decContentsDepth();
1298   }
1299
1300   endFile(ol);
1301   ol.popGeneratorState();
1302 }
1303
1304 //----------------------------------------------------------------------------
1305 static int countNamespaces()
1306 {
1307   int count=0;
1308   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1309   NamespaceDef *nd;
1310   for (;(nd=nli.current());++nli)
1311   {
1312     if (nd->isLinkableInProject()) count++;
1313   }
1314   return count;
1315 }
1316
1317 //----------------------------------------------------------------------------
1318
1319 void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly)
1320 {
1321   if (clDict)
1322   {
1323     ClassSDict::Iterator cli(*clDict);
1324     ClassDef *cd;
1325     for (;(cd=cli.current());++cli)
1326     {
1327       if (cd->getLanguage()==SrcLangExt_VHDL) 
1328       {
1329         if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || 
1330             (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS
1331            )// no architecture
1332         {
1333           continue;
1334         }
1335         if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS)
1336         {
1337           QCString n=cd->name();
1338           cd->setClassName(n.data());
1339         }         
1340       }
1341
1342       if (!globalOnly || 
1343            cd->getOuterScope()==0 || 
1344            cd->getOuterScope()==Doxygen::globalScope 
1345          ) 
1346       {
1347         int count=0;
1348         if (cd->getClassSDict())
1349         {
1350           ClassSDict::Iterator ccit(*cd->getClassSDict());
1351           ClassDef *ccd;
1352           for (;(ccd=ccit.current());++ccit)
1353           {
1354             if (ccd->isLinkableInProject() && ccd->templateMaster()==0) 
1355             {
1356               count++;
1357             }
1358           }
1359         }
1360         if (classVisibleInIndex(cd) && cd->templateMaster()==0) 
1361         { 
1362           ftv->addContentsItem(count>0,cd->displayName(FALSE),cd->getReference(),
1363               cd->getOutputFileBase(),cd->anchor(),FALSE,TRUE,cd); 
1364           if (addToIndex && 
1365               /*cd->partOfGroups()==0 &&*/
1366               (cd->getOuterScope()==0 || 
1367                cd->getOuterScope()->definitionType()!=Definition::TypeClass
1368               )
1369              )
1370           {
1371             addMembersToIndex(cd,LayoutDocManager::Class,
1372                               cd->displayName(FALSE),
1373                               cd->anchor(),
1374                               cd->partOfGroups()==0 && !cd->isSimple());
1375           }
1376           if (count>0)
1377           {
1378             ftv->incContentsDepth();
1379             writeClassTree(cd->getClassSDict(),ftv,addToIndex,FALSE);
1380             ftv->decContentsDepth();
1381           }
1382         }
1383       }
1384     }
1385   }
1386 }
1387
1388 static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv,
1389                                bool rootOnly,bool showClasses,bool addToIndex)
1390 {
1391   if (nsDict)
1392   {
1393     NamespaceSDict::Iterator nli(*nsDict);
1394     NamespaceDef *nd;
1395     for (nli.toFirst();(nd=nli.current());++nli)
1396     {
1397       if (nd->localName().find('@')==-1 && 
1398           (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
1399       {
1400
1401         bool hasChildren = namespaceHasVisibleChild(nd,showClasses);
1402         bool isLinkable  = nd->isLinkableInProject();
1403
1404         QCString ref; 
1405         QCString file; 
1406         if (isLinkable)
1407         {
1408           ref  = nd->getReference();
1409           file = nd->getOutputFileBase();
1410           if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK
1411           {
1412             file=file.replace(0,qstrlen("namespace"),"class");
1413           }
1414         }
1415
1416         if ((isLinkable && !showClasses) || hasChildren)
1417         {
1418           ftv->addContentsItem(hasChildren,nd->localName(),ref,file,0,FALSE,TRUE,nd); 
1419
1420           if (addToIndex)
1421           {
1422             Doxygen::indexList->addContentsItem(hasChildren,nd->localName(),ref,file,QCString(),
1423                 hasChildren && !file.isEmpty(),addToIndex);
1424           }
1425
1426           //printf("*** writeNamespaceTree count=%d addToIndex=%d showClasses=%d classCount=%d\n",
1427           //    count,addToIndex,showClasses,classCount);
1428           if (hasChildren)
1429           {
1430             if (addToIndex) Doxygen::indexList->incContentsDepth();
1431             ftv->incContentsDepth();
1432             writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,showClasses,addToIndex);
1433             if (showClasses) 
1434             {
1435               writeClassTree(nd->getClassSDict(),ftv,addToIndex,FALSE);
1436             }
1437             ftv->decContentsDepth();
1438             if (addToIndex) Doxygen::indexList->decContentsDepth();
1439           }
1440         }
1441       }
1442     }
1443   }
1444 }
1445
1446
1447 static void writeNamespaceIndex(OutputList &ol)
1448 {
1449   if (documentedNamespaces==0) return;
1450   ol.pushGeneratorState();
1451   ol.disable(OutputGenerator::Man);
1452   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceList);
1453   if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Namespaces); // fall back
1454   QCString title = lne ? lne->title() : theTranslator->trNamespaceList();
1455   bool addToIndex = lne==0 || lne->visible();
1456   startFile(ol,"namespaces",0,title,HLI_Namespaces);
1457   startTitle(ol,0);
1458   ol.parseText(title);
1459   endTitle(ol,0,0);
1460   ol.startContents();
1461   ol.startTextBlock();
1462   ol.parseText(lne ? lne->intro() : theTranslator->trNamespaceListDescription(Config_getBool("EXTRACT_ALL")));
1463   ol.endTextBlock();
1464
1465   bool first=TRUE;
1466
1467   // ---------------
1468   // Linear namespace index for Latex/RTF
1469   // ---------------
1470   ol.pushGeneratorState();
1471   ol.disable(OutputGenerator::Html);
1472   
1473   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1474   NamespaceDef *nd;
1475   for (nli.toFirst();(nd=nli.current());++nli)
1476   {
1477     if (nd->isLinkableInProject())
1478     {
1479       if (first)
1480       {
1481         ol.startIndexList();
1482         first=FALSE;
1483       }
1484       //ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name());
1485       ol.startIndexKey();
1486       if (nd->getLanguage()==SrcLangExt_VHDL)
1487       {
1488         ol.writeObjectLink(0, nd->getOutputFileBase().replace(0,qstrlen("namespace"),"class"),0,nd->displayName());
1489       }
1490       else
1491       {
1492         ol.writeObjectLink(0,nd->getOutputFileBase(),0,nd->displayName());
1493       }
1494       ol.endIndexKey();
1495
1496       bool hasBrief = !nd->briefDescription().isEmpty();
1497       ol.startIndexValue(hasBrief);
1498       if (hasBrief)
1499       {
1500         //ol.docify(" (");
1501         ol.generateDoc(
1502                  nd->briefFile(),nd->briefLine(),
1503                  nd,0,
1504                  nd->briefDescription(TRUE),
1505                  FALSE, // index words
1506                  FALSE, // isExample
1507                  0,     // example name
1508                  TRUE,  // single line
1509                  TRUE   // link from index
1510                 );
1511         //ol.docify(")");
1512       }
1513       ol.endIndexValue(nd->getOutputFileBase(),hasBrief);
1514
1515     }
1516   }
1517   if (!first) ol.endIndexList();
1518
1519   ol.popGeneratorState();
1520
1521   // ---------------
1522   // Hierarchical namespace index for HTML
1523   // ---------------
1524   ol.pushGeneratorState(); 
1525   ol.disableAllBut(OutputGenerator::Html);
1526
1527   {
1528     if (addToIndex)
1529     {
1530       Doxygen::indexList->addContentsItem(TRUE,title,0,"namespaces",0,TRUE,TRUE); 
1531       Doxygen::indexList->incContentsDepth();
1532     }
1533     FTVHelp* ftv = new FTVHelp(FALSE);
1534     writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,FALSE,addToIndex);
1535     QGString outStr;
1536     FTextStream t(&outStr);
1537     ftv->generateTreeViewInline(t);
1538     ol.writeString(outStr);
1539     delete ftv;
1540     if (addToIndex)
1541     {
1542       Doxygen::indexList->decContentsDepth();
1543     }
1544   }
1545
1546   ol.popGeneratorState();
1547   // ------
1548
1549   endFile(ol);
1550   ol.popGeneratorState();
1551 }
1552
1553 //----------------------------------------------------------------------------
1554
1555 static int countAnnotatedClasses(int *cp)
1556 {
1557   int count=0;
1558   int countPrinted=0;
1559   ClassSDict::Iterator cli(*Doxygen::classSDict);
1560   ClassDef *cd;
1561   for (;(cd=cli.current());++cli)
1562   {
1563     if (cd->isLinkableInProject() && cd->templateMaster()==0) 
1564     { 
1565       if (!cd->isEmbeddedInOuterScope())
1566       {
1567         countPrinted++;
1568       }
1569       count++; 
1570     }
1571   }
1572   *cp = countPrinted;
1573   return count;
1574 }
1575
1576
1577 static void writeAnnotatedClassList(OutputList &ol)
1578 {
1579   //LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList);
1580   //bool addToIndex = lne==0 || lne->visible();
1581
1582   ol.startIndexList(); 
1583   ClassSDict::Iterator cli(*Doxygen::classSDict);
1584   ClassDef *cd;
1585   
1586   for (cli.toFirst();(cd=cli.current());++cli)
1587   {
1588     if (cd->getLanguage()==SrcLangExt_VHDL && 
1589         ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || 
1590          (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
1591        ) // no architecture
1592     {
1593       continue;
1594     }
1595  
1596     ol.pushGeneratorState();
1597     if (cd->isEmbeddedInOuterScope())
1598     {
1599       ol.disable(OutputGenerator::Latex);
1600       ol.disable(OutputGenerator::RTF);
1601     }
1602     if (cd->isLinkableInProject() && cd->templateMaster()==0)
1603     {
1604       QCString type=cd->compoundTypeString();
1605       ol.startIndexKey();
1606       if (cd->getLanguage()==SrcLangExt_VHDL)
1607       {
1608         QCString prot= VhdlDocGen::getProtectionName((VhdlDocGen::VhdlClasses)cd->protection());
1609         ol.docify(prot.data());
1610         ol.writeString(" ");
1611       }
1612       ol.writeObjectLink(0,cd->getOutputFileBase(),cd->anchor(),cd->displayName());
1613       ol.endIndexKey();
1614       bool hasBrief = !cd->briefDescription().isEmpty();
1615       ol.startIndexValue(hasBrief);
1616       if (hasBrief)
1617       {
1618         ol.generateDoc(
1619                  cd->briefFile(),cd->briefLine(),
1620                  cd,0,
1621                  cd->briefDescription(TRUE),
1622                  FALSE,  // indexWords
1623                  FALSE,  // isExample
1624                  0,     // example name
1625                  TRUE,  // single line
1626                  TRUE   // link from index
1627                 );
1628       }
1629       ol.endIndexValue(cd->getOutputFileBase(),hasBrief);
1630
1631       //if (addToIndex)
1632       //{
1633       //  addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(),cd->anchor());
1634       //}
1635     }
1636     ol.popGeneratorState();
1637   }
1638   ol.endIndexList();
1639 }
1640
1641 static QCString letterToLabel(uint startLetter)
1642 {
1643   char s[10];
1644   if (startLetter>0x20 && startLetter<=0x7f) // printable ASCII character
1645   {
1646     s[0]=(char)startLetter;
1647     s[1]=0;
1648   }
1649   else
1650   {
1651     const char hex[]="0123456789abcdef";
1652     int i=0;
1653     s[i++]='0';
1654     s[i++]='x';
1655     if (startLetter>(1<<24)) // 4 byte character
1656     {
1657       s[i++]=hex[(startLetter>>28)&0xf];
1658       s[i++]=hex[(startLetter>>24)&0xf];
1659     }
1660     if (startLetter>(1<<16)) // 3 byte character
1661     {
1662       s[i++]=hex[(startLetter>>20)&0xf];
1663       s[i++]=hex[(startLetter>>16)&0xf];
1664     }
1665     if (startLetter>(1<<8)) // 2 byte character
1666     {
1667       s[i++]=hex[(startLetter>>12)&0xf];
1668       s[i++]=hex[(startLetter>>8)&0xf];
1669     }
1670     // one byte character
1671     s[i++]=hex[(startLetter>>4)&0xf];
1672     s[i++]=hex[(startLetter>>0)&0xf];
1673     s[i++]=0;
1674   }
1675   return s;
1676 }
1677
1678 //----------------------------------------------------------------------------
1679
1680 /** Special class list where sorting takes IGNORE_PREFIX into account. */
1681 class PrefixIgnoreClassList : public ClassList
1682 {
1683   public:
1684     typedef ClassDef ElementType;
1685     PrefixIgnoreClassList(uint letter) : m_letter(letter) {}
1686     uint letter() const { return m_letter; }
1687   private:
1688     virtual int compareValue(const ClassDef *c1, const ClassDef *c2) const
1689     {
1690       QCString n1 = c1->className();
1691       QCString n2 = c2->className();
1692       return qstricmp (n1.data()+getPrefixIndex(n1), n2.data()+getPrefixIndex(n2));
1693     }
1694     uint m_letter;
1695 };
1696
1697 /** Class representing a cell in the alphabetical class index. */
1698 class AlphaIndexTableCell
1699 {
1700   public:
1701     AlphaIndexTableCell(int row,int col,uint letter,ClassDef *cd) : 
1702       m_letter(letter), m_class(cd), m_row(row), m_col(col) 
1703     { //printf("AlphaIndexTableCell(%d,%d,%c,%s)\n",row,col,letter!=0 ? letter: '-',
1704       //       cd!=(ClassDef*)0x8 ? cd->name().data() : "<null>"); 
1705     }
1706
1707     ClassDef *classDef() const { return m_class; }
1708     uint letter()        const { return m_letter; }
1709     int row()            const { return m_row; }
1710     int column()         const { return m_col; }
1711
1712   private:
1713     uint m_letter;
1714     ClassDef *m_class;
1715     int m_row;
1716     int m_col;
1717 };
1718
1719 /** Class representing a row in the alphabetical class index. */
1720 class AlphaIndexTableRows : public QList<AlphaIndexTableCell>
1721 {
1722   public:
1723     AlphaIndexTableRows() { setAutoDelete(TRUE); }
1724 };
1725
1726 /** Iterator for the cells in a row of the alphabetical class index. */
1727 class AlphaIndexTableRowsIterator : public QListIterator<AlphaIndexTableCell>
1728 {
1729   public:
1730     AlphaIndexTableRowsIterator(const AlphaIndexTableRows &list) : 
1731       QListIterator<AlphaIndexTableCell>(list) {}
1732 };
1733
1734 /** Class representing the columns in the alphabetical class index. */
1735 class AlphaIndexTableColumns : public QList<AlphaIndexTableRows>
1736 {
1737   public:
1738     AlphaIndexTableColumns() { setAutoDelete(TRUE); }
1739 };
1740
1741 class UsedIndexLetters : public SIntDict<uint>
1742 {
1743   public:
1744     UsedIndexLetters() : SIntDict<uint>(257) { setAutoDelete(TRUE); }
1745     void add(uint letter)
1746     {
1747       uint *v = find(letter);
1748       if (v==0)
1749       {
1750         append(letter,new uint(letter));
1751       }
1752     }
1753   private:
1754     int compareValues( const uint *p1, const uint *p2) const
1755     {
1756       return (int)*p1 - (int)*p2; // subtracting is done by int not uint.
1757     }
1758 };
1759
1760 // write an alphabetical index of all class with a header for each letter
1761 static void writeAlphabeticalClassList(OutputList &ol)
1762 {
1763   // What starting letters are used
1764   UsedIndexLetters indexLettersUsed;
1765
1766   // first count the number of headers
1767   ClassSDict::Iterator cli(*Doxygen::classSDict);
1768   ClassDef *cd;
1769   uint startLetter=0;
1770   int headerItems=0;
1771   for (;(cd=cli.current());++cli)
1772   {
1773     if (cd->isLinkableInProject() && cd->templateMaster()==0)
1774     {
1775       if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
1776         continue;
1777              
1778       int index = getPrefixIndex(cd->className());
1779       //printf("name=%s index=%d %d\n",cd->className().data(),index,cd->protection());
1780       startLetter=getUtf8CodeToUpper(cd->className(),index);
1781       indexLettersUsed.add(startLetter);
1782     }
1783   }
1784   indexLettersUsed.sort();
1785
1786   // write quick link index (row of letters)
1787   QCString alphaLinks = "<div class=\"qindex\">";
1788   SIntDict<uint>::Iterator it(indexLettersUsed);
1789   uint *pLetter;
1790   for (it.toFirst();(pLetter=it.current());++it)
1791   {
1792     if (headerItems) alphaLinks += "&#160;|&#160;";
1793     headerItems++;
1794     QCString li = letterToLabel(*pLetter);
1795     QCString ls = QString(QChar(*pLetter)).utf8();
1796     alphaLinks += (QCString)"<a class=\"qindex\" href=\"#letter_" + 
1797                   li + "\">" + 
1798                   ls + "</a>";
1799   }
1800   alphaLinks += "</div>\n";
1801   ol.writeString(alphaLinks);
1802
1803
1804   // the number of columns in the table
1805   const int columns = Config_getInt("COLS_IN_ALPHA_INDEX");
1806
1807   int i,j;
1808   int totalItems = headerItems*2 + annotatedClasses;      // number of items in the table (headers span 2 items)
1809   int rows = (totalItems + columns - 1)/columns;          // number of rows in the table
1810
1811   //printf("headerItems=%d totalItems=%d columns=%d rows=%d itemsInLastRow=%d\n",
1812   //    headerItems,totalItems,columns,rows,itemsInLastRow);
1813
1814   // Keep a list of classes for each starting letter
1815   LetterToIndexMap<PrefixIgnoreClassList> classesByLetter;
1816   AlphaIndexTableColumns tableColumns;
1817
1818   // fill the columns with the class list (row elements in each column,
1819   // expect for the columns with number >= itemsInLastRow, which get one
1820   // item less.
1821   //int icount=0;
1822   startLetter=0;
1823   for (cli.toFirst();(cd=cli.current());++cli)
1824   {
1825     if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
1826       continue;
1827     
1828     if (cd->isLinkableInProject() && cd->templateMaster()==0)
1829     {
1830       int index = getPrefixIndex(cd->className());
1831       startLetter=getUtf8Code(cd->className(),index);
1832       // Do some sorting again, since the classes are sorted by name with 
1833       // prefix, which should be ignored really.
1834       if (cd->getLanguage()==SrcLangExt_VHDL)
1835       {
1836         if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS )// no architecture
1837         {
1838           classesByLetter.append(startLetter,cd);
1839         }
1840       }
1841       else
1842       {
1843         classesByLetter.append(startLetter,cd);
1844       }
1845     }
1846   }
1847
1848   #define NEXT_ROW()                           \
1849     do                                         \
1850     {                                          \
1851       if (row>maxRows) maxRows=row;            \
1852       if (row>=rows && col<columns)            \
1853       {                                        \
1854         col++;                                 \
1855         row=0;                                 \
1856         tableRows = new AlphaIndexTableRows;   \
1857         tableColumns.append(tableRows);        \
1858       }                                        \
1859     }                                          \
1860     while(0)                                   \
1861
1862   AlphaIndexTableRows *tableRows = new AlphaIndexTableRows;
1863   tableColumns.append(tableRows);
1864   int col=0,row=0,maxRows=0;
1865   PrefixIgnoreClassList *cl;
1866   SIntDict<PrefixIgnoreClassList>::Iterator lit(classesByLetter);
1867   for (lit.toFirst();(cl=lit.current());++lit)
1868   {
1869     uint l = cl->letter();
1870     // add special header cell
1871     tableRows->append(new AlphaIndexTableCell(row,col,l,(ClassDef*)0x8));
1872     row++;
1873     tableRows->append(new AlphaIndexTableCell(row,col,0,(ClassDef*)0x8));
1874     row++;
1875     ClassListIterator cit(*cl);
1876     cit.toFirst();
1877     ClassDef *cd = cit.current();
1878     ++cit;
1879     tableRows->append(new AlphaIndexTableCell(row,col,0,cd));
1880     row++; 
1881     NEXT_ROW();
1882     for (;(cd=cit.current()); ++cit)
1883     {
1884       // add normal cell
1885       tableRows->append(new AlphaIndexTableCell(row,col,0,cd));
1886       row++;
1887       NEXT_ROW();
1888     }
1889   }
1890
1891   // create row iterators for each column
1892   AlphaIndexTableRowsIterator **colIterators = new AlphaIndexTableRowsIterator*[columns];
1893   for (i=0;i<columns;i++)
1894   {
1895     if (i<(int)tableColumns.count())
1896     {
1897       colIterators[i] = new AlphaIndexTableRowsIterator(*tableColumns.at(i));
1898     }
1899     else // empty column
1900     {
1901       colIterators[i] = 0;
1902     }
1903   }
1904
1905   ol.writeString("<table style=\"margin: 10px; white-space: nowrap;\" align=\"center\" width=\"95%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n");
1906   // generate table
1907   for (i=0;i<=maxRows;i++) // foreach table row
1908   {
1909     //printf("writing row %d\n",i);
1910     //ol.nextTableRow();
1911     ol.writeString("<tr>");
1912     // the last column may contain less items then the others
1913     //int colsInRow = (i<rows-1) ? columns : itemsInLastRow; 
1914     //printf("row [%d]\n",i);
1915     for (j=0;j<columns;j++) // foreach table column
1916     {
1917       if (colIterators[j])
1918       {
1919         AlphaIndexTableCell *cell = colIterators[j]->current();
1920         if (cell)
1921         {
1922           if (cell->row()==i)
1923           {
1924             if (cell->letter()!=0)
1925             {
1926               QCString s = letterToLabel(cell->letter());
1927               ol.writeString("<td rowspan=\"2\" valign=\"bottom\">");
1928               ol.writeString("<a name=\"letter_");
1929               ol.writeString(s);
1930               ol.writeString("\"></a>");
1931               ol.writeString("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
1932                   "<tr>"
1933                   "<td><div class=\"ah\">&#160;&#160;"); 
1934               ol.writeString(QString(QChar(cell->letter())).utf8());
1935               ol.writeString(         "&#160;&#160;</div>"
1936                   "</td>"
1937                   "</tr>"
1938                   "</table>\n");
1939             }
1940             else if (cell->classDef()!=(ClassDef*)0x8)
1941             {
1942               cd = cell->classDef();
1943               ol.writeString("<td valign=\"top\">");
1944               QCString namesp,cname;
1945               //if (cd->getNamespaceDef()) namesp=cd->getNamespaceDef()->displayName();
1946               //QCString cname=cd->className();
1947               extractNamespaceName(cd->name(),cname,namesp);
1948               QCString nsDispName;
1949               SrcLangExt lang = cd->getLanguage();
1950               QCString sep = getLanguageSpecificSeparator(lang);
1951               if (sep!="::")
1952               {
1953                 nsDispName=substitute(namesp,"::",sep);
1954                 cname=substitute(cname,"::",sep);
1955               }
1956               else
1957               {
1958                 nsDispName=namesp;
1959               }
1960
1961               ol.writeObjectLink(cd->getReference(),
1962                   cd->getOutputFileBase(),cd->anchor(),cname);
1963               if (!namesp.isEmpty())
1964               {
1965                 ol.docify(" (");
1966                 NamespaceDef *nd = getResolvedNamespace(namesp);
1967                 if (nd && nd->isLinkable())
1968                 {
1969                   ol.writeObjectLink(nd->getReference(),
1970                       nd->getOutputFileBase(),0,nsDispName);
1971                 }
1972                 else
1973                 {
1974                   ol.docify(nsDispName);
1975                 }
1976                 ol.docify(")");
1977               }
1978               ol.writeNonBreakableSpace(3);
1979             }
1980             ++(*colIterators[j]);
1981             if (cell->letter()!=0 || cell->classDef()!=(ClassDef*)0x8)
1982             {
1983               ol.writeString("</td>");
1984             }
1985           }
1986         }
1987         else
1988         {
1989           ol.writeString("<td></td>");
1990         }
1991       }
1992     }
1993     ol.writeString("</tr>\n");
1994   }
1995   ol.writeString("</table>\n");
1996   
1997   ol.writeString(alphaLinks);
1998
1999   // release the temporary memory
2000   for (i=0;i<columns;i++)
2001   {
2002     delete colIterators[i];
2003   }
2004   delete[] colIterators;
2005 }
2006
2007 //----------------------------------------------------------------------------
2008
2009 static void writeAlphabeticalIndex(OutputList &ol)
2010 {
2011   if (annotatedClasses==0) return;
2012   ol.pushGeneratorState();
2013   ol.disableAllBut(OutputGenerator::Html);
2014   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassIndex);
2015   QCString title = lne ? lne->title() : theTranslator->trCompoundIndex();
2016   bool addToIndex = lne==0 || lne->visible();
2017
2018   startFile(ol,"classes",0,title,HLI_Classes); 
2019
2020   startTitle(ol,0);
2021   ol.parseText(title);
2022   endTitle(ol,0,0);
2023
2024   if (addToIndex)
2025   {
2026     Doxygen::indexList->addContentsItem(FALSE,title,0,"classes",0,FALSE,TRUE); 
2027   }
2028
2029   ol.startContents();
2030   writeAlphabeticalClassList(ol);
2031   endFile(ol); // contains ol.endContents()
2032
2033   ol.popGeneratorState();
2034 }
2035
2036 //----------------------------------------------------------------------------
2037
2038 static void writeAnnotatedIndex(OutputList &ol)
2039 {
2040   //printf("writeAnnotatedIndex: count=%d printed=%d\n",
2041   //    annotatedClasses,annotatedClassesPrinted);
2042   if (annotatedClasses==0) return;
2043   
2044   ol.pushGeneratorState();
2045   ol.disable(OutputGenerator::Man);
2046   if (annotatedClassesPrinted==0)
2047   {
2048     ol.disable(OutputGenerator::Latex);
2049     ol.disable(OutputGenerator::RTF);
2050   }
2051   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList);
2052   if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Classes); // fall back
2053   QCString title = lne ? lne->title() : theTranslator->trCompoundList();
2054   bool addToIndex = lne==0 || lne->visible();
2055
2056   
2057   startFile(ol,"annotated",0,title,HLI_Annotated);
2058
2059   startTitle(ol,0);
2060   ol.parseText(title);
2061   endTitle(ol,0,0);
2062
2063   ol.startContents();
2064
2065   ol.startTextBlock();
2066   ol.parseText(lne ? lne->intro() : theTranslator->trCompoundListDescription());
2067   ol.endTextBlock();
2068
2069   // ---------------
2070   // Linear class index for Latex/RTF
2071   // ---------------
2072   ol.pushGeneratorState();
2073   ol.disable(OutputGenerator::Html);
2074   Doxygen::indexList->disable();
2075
2076   writeAnnotatedClassList(ol);
2077
2078   Doxygen::indexList->enable();
2079   ol.popGeneratorState();
2080
2081   // ---------------
2082   // Hierarchical class index for HTML
2083   // ---------------
2084   ol.pushGeneratorState(); 
2085   ol.disableAllBut(OutputGenerator::Html);
2086
2087   {
2088     if (addToIndex)
2089     {
2090       Doxygen::indexList->addContentsItem(TRUE,title,0,"annotated",0,TRUE,TRUE); 
2091       Doxygen::indexList->incContentsDepth();
2092     }
2093     FTVHelp* ftv = new FTVHelp(FALSE);
2094     writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex);
2095     writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE);
2096     QGString outStr;
2097     FTextStream t(&outStr);
2098     ftv->generateTreeViewInline(t);
2099     ol.writeString(outStr);
2100     delete ftv;
2101     if (addToIndex)
2102     {
2103       Doxygen::indexList->decContentsDepth();
2104     }
2105   }
2106
2107   ol.popGeneratorState();
2108   // ------
2109   
2110   endFile(ol); // contains ol.endContents()
2111   ol.popGeneratorState();
2112 }
2113
2114 //----------------------------------------------------------------------------
2115 static void writeClassLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
2116                              QCString &prevClassName)
2117 {
2118   ClassDef *cd=md->getClassDef();
2119   if ( cd && prevClassName!=cd->displayName())
2120   {
2121     ol.docify(separator);
2122     ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2123         cd->displayName());
2124     ol.writeString("\n");
2125     prevClassName = cd->displayName();
2126   }
2127 }
2128
2129 static void writeFileLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
2130                              QCString &prevFileName)
2131 {
2132   FileDef *fd=md->getFileDef();
2133   if (fd && prevFileName!=fd->name())
2134   {
2135     ol.docify(separator);
2136     ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2137         fd->name());
2138     ol.writeString("\n");
2139     prevFileName = fd->name();
2140   }
2141 }
2142
2143 static void writeNamespaceLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
2144                              QCString &prevNamespaceName)
2145 {
2146   NamespaceDef *nd=md->getNamespaceDef();
2147   if (nd && prevNamespaceName!=nd->name())
2148   {
2149     ol.docify(separator);
2150     ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2151         nd->name());
2152     ol.writeString("\n");
2153     prevNamespaceName = nd->name();
2154   }
2155 }
2156
2157 static void writeMemberList(OutputList &ol,bool useSections,int page,
2158                             const LetterToIndexMap<MemberIndexList> &memberLists,
2159                             DefinitionIntf::DefType type)
2160 {
2161   ASSERT((int)type<3);
2162
2163   typedef void (*writeLinkForMember_t)(OutputList &ol,MemberDef *md,const char *separator,
2164                                    QCString &prevNamespaceName);
2165
2166   // each index tab has its own write function
2167   static writeLinkForMember_t writeLinkForMemberMap[3] = 
2168   { 
2169     &writeClassLinkForMember, 
2170     &writeFileLinkForMember,
2171     &writeNamespaceLinkForMember
2172   };
2173   QCString prevName;
2174   QCString prevDefName;
2175   bool first=TRUE;
2176   bool firstSection=TRUE;
2177   bool firstItem=TRUE;
2178   MemberIndexList *ml;
2179   SIntDict<MemberIndexList>::Iterator it(memberLists);
2180   for (it.toFirst();(ml=it.current());++it)
2181   {
2182     if (page!=-1)
2183     {
2184       ml = memberLists[page];
2185       it.toLast();
2186     }
2187     if (ml==0 || ml->count()==0) continue;
2188     ml->sort();
2189     QListIterator<MemberDef> mli(*ml);
2190     MemberDef *md;
2191     for (mli.toFirst();(md=mli.current());++mli)
2192     {
2193       const char *sep;
2194       bool isFunc=!md->isObjCMethod() && 
2195         (md->isFunction() || md->isSlot() || md->isSignal()); 
2196       QCString name=md->name();
2197       int startIndex = getPrefixIndex(name);
2198       if (QCString(name.data()+startIndex)!=prevName) // new entry
2199       {
2200         if ((prevName.isEmpty() || 
2201             tolower(name.at(startIndex))!=tolower(prevName.at(0))) && 
2202             useSections) // new section
2203         {
2204           if (!firstItem)    ol.endItemListItem();
2205           if (!firstSection) ol.endItemList();
2206           QCString cs = letterToLabel(ml->letter());
2207           QCString cl = QString(QChar(ml->letter())).utf8();
2208           QCString anchor=(QCString)"index_"+cs;
2209           QCString title=(QCString)"- "+cl+" -";
2210           ol.startSection(anchor,title,SectionInfo::Subsection);
2211           ol.docify(title);
2212           ol.endSection(anchor,SectionInfo::Subsection);
2213           ol.startItemList();
2214           firstSection=FALSE;
2215           firstItem=TRUE;
2216         }
2217         else if (!useSections && first)
2218         {
2219           ol.startItemList();
2220           first=FALSE;
2221         }
2222
2223         // member name
2224         if (!firstItem) ol.endItemListItem();
2225         ol.startItemListItem();
2226         firstItem=FALSE;
2227         ol.docify(name);
2228         if (isFunc) ol.docify("()");
2229         ol.writeString("\n");
2230
2231         // link to class
2232         prevDefName="";
2233         sep = ": ";
2234         prevName = name.data()+startIndex;
2235       }
2236       else // same entry
2237       {
2238         sep = ", ";
2239         // link to class for other members with the same name
2240       }
2241       // write the link for the specific list type
2242       writeLinkForMemberMap[(int)type](ol,md,sep,prevDefName);
2243     }
2244   }
2245   if (!firstItem) ol.endItemListItem();
2246   ol.endItemList();
2247 }
2248
2249 //----------------------------------------------------------------------------
2250
2251 void initClassMemberIndices()
2252 {
2253   int j=0;
2254   for (j=0;j<CMHL_Total;j++)
2255   {
2256     documentedClassMembers[j]=0;
2257     g_memberIndexLetterUsed[j].clear();
2258   }
2259 }
2260
2261 void addClassMemberNameToIndex(MemberDef *md)
2262 {
2263   static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS");
2264   ClassDef *cd=0;
2265
2266  
2267   
2268   if (md->isLinkableInProject() && 
2269       (cd=md->getClassDef())    && 
2270       cd->isLinkableInProject() &&
2271       cd->templateMaster()==0)
2272   {
2273     QCString n = md->name();
2274     int index = getPrefixIndex(n);
2275     uint letter = getUtf8CodeToLower(n,index);
2276     if (!n.isEmpty()) 
2277     {
2278       bool isFriendToHide = hideFriendCompounds &&
2279         (QCString(md->typeString())=="friend class" || 
2280          QCString(md->typeString())=="friend struct" ||
2281          QCString(md->typeString())=="friend union");
2282       if (!(md->isFriend() && isFriendToHide) &&
2283           (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2284          )
2285       {
2286         g_memberIndexLetterUsed[CMHL_All].append(letter,md);
2287         documentedClassMembers[CMHL_All]++;
2288       }
2289       if (md->isFunction()  || md->isSlot() || md->isSignal())
2290       {
2291         g_memberIndexLetterUsed[CMHL_Functions].append(letter,md);
2292         documentedClassMembers[CMHL_Functions]++;
2293       }
2294       else if (md->isVariable())
2295       {
2296         g_memberIndexLetterUsed[CMHL_Variables].append(letter,md);
2297         documentedClassMembers[CMHL_Variables]++;
2298       }
2299       else if (md->isTypedef())
2300       {
2301         g_memberIndexLetterUsed[CMHL_Typedefs].append(letter,md);
2302         documentedClassMembers[CMHL_Typedefs]++;
2303       }
2304       else if (md->isEnumerate())
2305       {
2306         g_memberIndexLetterUsed[CMHL_Enums].append(letter,md);
2307         documentedClassMembers[CMHL_Enums]++;
2308       }
2309       else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2310       {
2311         g_memberIndexLetterUsed[CMHL_EnumValues].append(letter,md);
2312         documentedClassMembers[CMHL_EnumValues]++;
2313       }
2314       else if (md->isProperty())
2315       {
2316         g_memberIndexLetterUsed[CMHL_Properties].append(letter,md);
2317         documentedClassMembers[CMHL_Properties]++;
2318       }
2319       else if (md->isEvent())
2320       {
2321         g_memberIndexLetterUsed[CMHL_Events].append(letter,md);
2322         documentedClassMembers[CMHL_Events]++;
2323       }
2324       else if (md->isRelated() || md->isForeign() ||
2325                (md->isFriend() && !isFriendToHide))
2326       {
2327         g_memberIndexLetterUsed[CMHL_Related].append(letter,md);
2328         documentedClassMembers[CMHL_Related]++;
2329       }
2330     }
2331   }
2332 }
2333
2334 //----------------------------------------------------------------------------
2335
2336 void initNamespaceMemberIndices()
2337 {
2338   int j=0;
2339   for (j=0;j<NMHL_Total;j++)
2340   {
2341     documentedNamespaceMembers[j]=0;
2342     g_namespaceIndexLetterUsed[j].clear();
2343   }
2344 }
2345
2346 void addNamespaceMemberNameToIndex(MemberDef *md)
2347 {
2348   NamespaceDef *nd=md->getNamespaceDef();
2349   if (nd && nd->isLinkableInProject() && md->isLinkableInProject())
2350   {
2351     QCString n = md->name();
2352     int index = getPrefixIndex(n);
2353     uint letter = getUtf8CodeToLower(n,index);
2354     if (!n.isEmpty())
2355     {
2356       if (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2357       {
2358         g_namespaceIndexLetterUsed[NMHL_All].append(letter,md);
2359         documentedNamespaceMembers[NMHL_All]++;
2360       }
2361
2362       if (md->isFunction()) 
2363       {
2364         g_namespaceIndexLetterUsed[NMHL_Functions].append(letter,md);
2365         documentedNamespaceMembers[NMHL_Functions]++;
2366       }
2367       else if (md->isVariable()) 
2368       {
2369         g_namespaceIndexLetterUsed[NMHL_Variables].append(letter,md);
2370         documentedNamespaceMembers[NMHL_Variables]++;
2371       }
2372       else if (md->isTypedef())
2373       {
2374         g_namespaceIndexLetterUsed[NMHL_Typedefs].append(letter,md);
2375         documentedNamespaceMembers[NMHL_Typedefs]++;
2376       }
2377       else if (md->isEnumerate())
2378       {
2379         g_namespaceIndexLetterUsed[NMHL_Enums].append(letter,md);
2380         documentedNamespaceMembers[NMHL_Enums]++;
2381       }
2382       else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2383       {
2384         g_namespaceIndexLetterUsed[NMHL_EnumValues].append(letter,md);
2385         documentedNamespaceMembers[NMHL_EnumValues]++;
2386       }
2387     }
2388   }
2389 }
2390
2391 //----------------------------------------------------------------------------
2392
2393 void initFileMemberIndices()
2394 {
2395   int j=0;
2396   for (j=0;j<NMHL_Total;j++)
2397   {
2398     documentedFileMembers[j]=0;
2399     g_fileIndexLetterUsed[j].clear();
2400   }
2401 }
2402
2403 void addFileMemberNameToIndex(MemberDef *md)
2404 {
2405   FileDef *fd=md->getFileDef();
2406   if (fd && fd->isLinkableInProject() && md->isLinkableInProject())
2407   {
2408     QCString n = md->name();
2409     int index = getPrefixIndex(n);
2410     uint letter = getUtf8CodeToLower(n,index);
2411     if (!n.isEmpty()) 
2412     {
2413       if (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2414       {
2415         g_fileIndexLetterUsed[FMHL_All].append(letter,md);
2416         documentedFileMembers[FMHL_All]++;
2417       }
2418
2419       if (md->isFunction()) 
2420       {
2421         g_fileIndexLetterUsed[FMHL_Functions].append(letter,md);
2422         documentedFileMembers[FMHL_Functions]++;
2423       }
2424       else if (md->isVariable()) 
2425       {
2426         g_fileIndexLetterUsed[FMHL_Variables].append(letter,md);
2427         documentedFileMembers[FMHL_Variables]++;
2428       }
2429       else if (md->isTypedef())
2430       {
2431         g_fileIndexLetterUsed[FMHL_Typedefs].append(letter,md);
2432         documentedFileMembers[FMHL_Typedefs]++;
2433       }
2434       else if (md->isEnumerate())
2435       {
2436         g_fileIndexLetterUsed[FMHL_Enums].append(letter,md);
2437         documentedFileMembers[FMHL_Enums]++;
2438       }
2439       else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2440       {
2441         g_fileIndexLetterUsed[FMHL_EnumValues].append(letter,md);
2442         documentedFileMembers[FMHL_EnumValues]++;
2443       }
2444       else if (md->isDefine())
2445       {
2446         g_fileIndexLetterUsed[FMHL_Defines].append(letter,md);
2447         documentedFileMembers[FMHL_Defines]++;
2448       }
2449     }
2450   }
2451 }
2452
2453 //----------------------------------------------------------------------------
2454
2455 static void writeQuickMemberIndex(OutputList &ol,
2456     const LetterToIndexMap<MemberIndexList> &charUsed,uint page,
2457     QCString fullName,bool multiPage)
2458 {
2459   bool first=TRUE;
2460   startQuickIndexList(ol,TRUE);
2461   SIntDict<MemberIndexList>::Iterator it(charUsed);
2462   MemberIndexList *ml;
2463   for (it.toFirst();(ml=it.current());++it)
2464   {
2465     uint i = ml->letter();
2466     QCString is = letterToLabel(i);
2467     QCString ci = QString(QChar(i)).utf8();
2468     QCString anchor;
2469     QCString extension=Doxygen::htmlFileExtension;
2470     if (!multiPage)
2471       anchor="#index_";
2472     else if (first) 
2473       anchor=fullName+extension+"#index_";
2474     else 
2475       anchor=fullName+"_"+letterToLabel(i)+extension+"#index_";
2476     startQuickIndexItem(ol,anchor+ci,i==page,TRUE,first);
2477     ol.writeString(is);
2478     endQuickIndexItem(ol);
2479     first=FALSE;
2480   }
2481   endQuickIndexList(ol);
2482 }
2483
2484 //----------------------------------------------------------------------------
2485
2486 /** Helper class representing a class member in the navigation menu. */
2487 struct CmhlInfo
2488 {
2489   CmhlInfo(const char *fn,const char *t) : fname(fn), title(t) {}
2490   const char *fname;
2491   QCString title;
2492 };
2493
2494 static const CmhlInfo *getCmhlInfo(int hl)
2495 {
2496   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
2497   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2498   static CmhlInfo cmhlInfo[] = 
2499   {
2500     CmhlInfo("functions",     theTranslator->trAll()),
2501     CmhlInfo("functions_func",
2502         fortranOpt ? theTranslator->trSubprograms() : 
2503         vhdlOpt    ? VhdlDocGen::trFunctionAndProc() :
2504                      theTranslator->trFunctions()),
2505     CmhlInfo("functions_vars",theTranslator->trVariables()),
2506     CmhlInfo("functions_type",theTranslator->trTypedefs()),
2507     CmhlInfo("functions_enum",theTranslator->trEnumerations()),
2508     CmhlInfo("functions_eval",theTranslator->trEnumerationValues()),
2509     CmhlInfo("functions_prop",theTranslator->trProperties()),
2510     CmhlInfo("functions_evnt",theTranslator->trEvents()),
2511     CmhlInfo("functions_rela",theTranslator->trRelatedFunctions())
2512   };
2513   return &cmhlInfo[hl];
2514 }
2515
2516 static void writeClassMemberIndexFiltered(OutputList &ol, ClassMemberHighlight hl)
2517 {
2518   if (documentedClassMembers[hl]==0) return;
2519
2520   static bool disableIndex     = Config_getBool("DISABLE_INDEX");
2521
2522   bool multiPageIndex=FALSE;
2523   if (documentedClassMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
2524   {
2525     multiPageIndex=TRUE;
2526   }
2527
2528   ol.pushGeneratorState();
2529   ol.disableAllBut(OutputGenerator::Html);
2530
2531   QCString extension=Doxygen::htmlFileExtension;
2532   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassMembers);
2533   QCString title = lne ? lne->title() : theTranslator->trCompoundMembers();
2534   if (hl!=CMHL_All) title+=(QCString)" - "+getCmhlInfo(hl)->title;
2535   bool addToIndex = lne==0 || lne->visible();
2536
2537   if (addToIndex)
2538   {
2539     Doxygen::indexList->addContentsItem(multiPageIndex,getCmhlInfo(hl)->title,0,
2540         getCmhlInfo(hl)->fname,0,multiPageIndex,TRUE);
2541     if (multiPageIndex) Doxygen::indexList->incContentsDepth();
2542   }
2543
2544   bool first=TRUE;
2545   SIntDict<MemberIndexList>::Iterator it(g_memberIndexLetterUsed[hl]);
2546   MemberIndexList *ml;
2547   for (it.toFirst();(ml=it.current());++it)
2548   {
2549     uint page = ml->letter();
2550     QCString fileName = getCmhlInfo(hl)->fname;
2551     if (multiPageIndex)
2552     { 
2553       if (!first)
2554       {
2555         fileName+="_"+letterToLabel(page);
2556       }
2557       QCString cs = QString(QChar(page)).utf8();
2558       if (addToIndex)
2559       {
2560         Doxygen::indexList->addContentsItem(FALSE,cs,0,fileName,0,FALSE,TRUE);
2561       }
2562     }
2563     bool quickIndex = documentedClassMembers[hl]>maxItemsBeforeQuickIndex;
2564
2565     ol.startFile(fileName+extension,0,title);
2566     ol.startQuickIndices();
2567     if (!disableIndex)
2568     {
2569       ol.writeQuickLinks(TRUE,HLI_Functions,0);
2570       startQuickIndexList(ol);
2571
2572       // index item for global member list
2573       startQuickIndexItem(ol,
2574           getCmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==CMHL_All,TRUE,first);
2575       ol.writeString(fixSpaces(getCmhlInfo(0)->title));
2576       endQuickIndexItem(ol);
2577
2578       int i;
2579       // index items per category member lists
2580       for (i=1;i<CMHL_Total;i++)
2581       {
2582         if (documentedClassMembers[i]>0)
2583         {
2584           startQuickIndexItem(ol,getCmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
2585           ol.writeString(fixSpaces(getCmhlInfo(i)->title));
2586           //printf("multiPageIndex=%d first=%d fileName=%s file=%s title=%s\n",
2587           //    multiPageIndex,first,fileName.data(),getCmhlInfo(i)->fname,getCmhlInfo(i)->title.data());
2588           endQuickIndexItem(ol);
2589         }
2590       }
2591
2592       endQuickIndexList(ol);
2593
2594       // quick alphabetical index
2595       if (quickIndex)
2596       {
2597         writeQuickMemberIndex(ol,g_memberIndexLetterUsed[hl],page,
2598             getCmhlInfo(hl)->fname,multiPageIndex);
2599       }
2600     }
2601     ol.endQuickIndices();
2602     ol.writeSplitBar(fileName);
2603     ol.writeSearchInfo();
2604
2605     ol.startContents();
2606
2607     if (hl==CMHL_All)
2608     {
2609       ol.startTextBlock();
2610       ol.parseText(lne ? lne->intro() : theTranslator->trCompoundMembersDescription(Config_getBool("EXTRACT_ALL")));
2611       ol.endTextBlock();
2612     }
2613     else
2614     {
2615       // hack to work around a mozilla bug, which refuses to switch to
2616       // normal lists otherwise
2617       ol.writeString("&#160;");
2618     }
2619
2620     writeMemberList(ol,quickIndex,
2621         multiPageIndex?page:-1,
2622         g_memberIndexLetterUsed[hl],
2623         Definition::TypeClass);
2624     endFile(ol);
2625     first=FALSE;
2626   }
2627
2628   if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
2629
2630   ol.popGeneratorState();
2631 }
2632
2633 static void writeClassMemberIndex(OutputList &ol)
2634 {
2635   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassMembers);
2636   bool addToIndex = lne==0 || lne->visible();
2637
2638   if (documentedClassMembers[CMHL_All]>0 && addToIndex)
2639   {
2640     Doxygen::indexList->addContentsItem(TRUE,lne ? lne->title() : theTranslator->trCompoundMembers(),0,"functions",0); 
2641     Doxygen::indexList->incContentsDepth();
2642   }
2643   writeClassMemberIndexFiltered(ol,CMHL_All);
2644   writeClassMemberIndexFiltered(ol,CMHL_Functions);
2645   writeClassMemberIndexFiltered(ol,CMHL_Variables);
2646   writeClassMemberIndexFiltered(ol,CMHL_Typedefs);
2647   writeClassMemberIndexFiltered(ol,CMHL_Enums);
2648   writeClassMemberIndexFiltered(ol,CMHL_EnumValues);
2649   writeClassMemberIndexFiltered(ol,CMHL_Properties);
2650   writeClassMemberIndexFiltered(ol,CMHL_Events);
2651   writeClassMemberIndexFiltered(ol,CMHL_Related);
2652   if (documentedClassMembers[CMHL_All]>0 && addToIndex)
2653   {
2654     Doxygen::indexList->decContentsDepth();
2655   }
2656
2657 }
2658
2659 //----------------------------------------------------------------------------
2660
2661 /** Helper class representing a file member in the navigation menu. */
2662 struct FmhlInfo 
2663 {
2664   FmhlInfo(const char *fn,const char *t) : fname(fn), title(t) {}
2665   const char *fname;
2666   QCString title;
2667 };
2668
2669 static const FmhlInfo *getFmhlInfo(int hl)
2670 {
2671   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
2672   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2673   static FmhlInfo fmhlInfo[] = 
2674   {
2675     FmhlInfo("globals",     theTranslator->trAll()),
2676     FmhlInfo("globals_func",
2677          fortranOpt ? theTranslator->trSubprograms()  : 
2678          vhdlOpt    ? VhdlDocGen::trFunctionAndProc() : 
2679                       theTranslator->trFunctions()),
2680     FmhlInfo("globals_vars",theTranslator->trVariables()),
2681     FmhlInfo("globals_type",theTranslator->trTypedefs()),
2682     FmhlInfo("globals_enum",theTranslator->trEnumerations()),
2683     FmhlInfo("globals_eval",theTranslator->trEnumerationValues()),
2684     FmhlInfo("globals_defs",theTranslator->trDefines())
2685   };
2686   return &fmhlInfo[hl];
2687 }
2688
2689 static void writeFileMemberIndexFiltered(OutputList &ol, FileMemberHighlight hl)
2690 {
2691   if (documentedFileMembers[hl]==0) return;
2692
2693   static bool disableIndex     = Config_getBool("DISABLE_INDEX");
2694
2695   bool multiPageIndex=FALSE;
2696   if (documentedFileMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
2697   {
2698     multiPageIndex=TRUE;
2699   }
2700
2701   ol.pushGeneratorState();
2702   ol.disableAllBut(OutputGenerator::Html);
2703
2704   QCString extension=Doxygen::htmlFileExtension;
2705   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileGlobals);
2706   QCString title = lne ? lne->title() : theTranslator->trFileMembers();
2707   bool addToIndex = lne==0 || lne->visible();
2708
2709   if (addToIndex)
2710   {
2711     Doxygen::indexList->addContentsItem(multiPageIndex,getFmhlInfo(hl)->title,0,
2712         getFmhlInfo(hl)->fname,0,multiPageIndex,TRUE);
2713     if (multiPageIndex) Doxygen::indexList->incContentsDepth();
2714   }
2715
2716   bool first=TRUE;
2717   SIntDict<MemberIndexList>::Iterator it(g_fileIndexLetterUsed[hl]);
2718   MemberIndexList *ml;
2719   for (it.toFirst();(ml=it.current());++it)
2720   {
2721     uint page = ml->letter();
2722     QCString fileName = getFmhlInfo(hl)->fname;
2723     if (multiPageIndex)
2724     {
2725       if (!first)
2726       {
2727         fileName+="_"+letterToLabel(page);
2728       }
2729       QCString cs = QString(QChar(page)).utf8();
2730       if (addToIndex)
2731       {
2732         Doxygen::indexList->addContentsItem(FALSE,cs,0,fileName,0,FALSE,TRUE);
2733       }
2734     }
2735     bool quickIndex = documentedFileMembers[hl]>maxItemsBeforeQuickIndex;
2736
2737     ol.startFile(fileName+extension,0,title);
2738     ol.startQuickIndices();
2739     if (!disableIndex)
2740     {
2741       ol.writeQuickLinks(TRUE,HLI_Globals,0);
2742       startQuickIndexList(ol);
2743
2744       // index item for all file member lists
2745       startQuickIndexItem(ol,
2746           getFmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==FMHL_All,TRUE,first);
2747       ol.writeString(fixSpaces(getFmhlInfo(0)->title));
2748       endQuickIndexItem(ol);
2749
2750       int i;
2751       // index items for per category member lists
2752       for (i=1;i<FMHL_Total;i++)
2753       {
2754         if (documentedFileMembers[i]>0)
2755         {
2756           startQuickIndexItem(ol,
2757               getFmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
2758           ol.writeString(fixSpaces(getFmhlInfo(i)->title));
2759           endQuickIndexItem(ol);
2760         }
2761       }
2762
2763       endQuickIndexList(ol);
2764
2765       if (quickIndex)
2766       {
2767         writeQuickMemberIndex(ol,g_fileIndexLetterUsed[hl],page,
2768             getFmhlInfo(hl)->fname,multiPageIndex);
2769       }
2770     }
2771     ol.endQuickIndices();
2772     ol.writeSplitBar(fileName);
2773     ol.writeSearchInfo();
2774
2775     ol.startContents();
2776
2777     if (hl==FMHL_All)
2778     {
2779       ol.startTextBlock();
2780       ol.parseText(lne ? lne->intro() : theTranslator->trFileMembersDescription(Config_getBool("EXTRACT_ALL")));
2781       ol.endTextBlock();
2782     }
2783     else
2784     {
2785       // hack to work around a mozilla bug, which refuses to switch to
2786       // normal lists otherwise
2787       ol.writeString("&#160;");
2788     }
2789
2790     writeMemberList(ol,quickIndex,
2791         multiPageIndex?page:-1,
2792         g_fileIndexLetterUsed[hl],
2793         Definition::TypeFile);
2794     endFile(ol);
2795     first=FALSE;
2796   }
2797   if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
2798   ol.popGeneratorState();
2799 }
2800
2801 static void writeFileMemberIndex(OutputList &ol)
2802 {
2803   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileGlobals);
2804   bool addToIndex = lne==0 || lne->visible();
2805   if (documentedFileMembers[FMHL_All]>0 && addToIndex)
2806   {
2807     Doxygen::indexList->addContentsItem(FALSE,lne ? lne->title() : theTranslator->trFileMembers(),0,"globals",0); 
2808     Doxygen::indexList->incContentsDepth();
2809   }
2810   writeFileMemberIndexFiltered(ol,FMHL_All);
2811   writeFileMemberIndexFiltered(ol,FMHL_Functions);
2812   writeFileMemberIndexFiltered(ol,FMHL_Variables);
2813   writeFileMemberIndexFiltered(ol,FMHL_Typedefs);
2814   writeFileMemberIndexFiltered(ol,FMHL_Enums);
2815   writeFileMemberIndexFiltered(ol,FMHL_EnumValues);
2816   writeFileMemberIndexFiltered(ol,FMHL_Defines);
2817   if (documentedFileMembers[FMHL_All]>0 && addToIndex)
2818   {
2819     Doxygen::indexList->decContentsDepth();
2820   }
2821
2822 }
2823
2824 //----------------------------------------------------------------------------
2825
2826 /** Helper class representing a namespace member in the navigation menu. */
2827 struct NmhlInfo
2828 {
2829   NmhlInfo(const char *fn,const char *t) : fname(fn), title(t) {}
2830   const char *fname;
2831   QCString title;
2832 };
2833
2834 static const NmhlInfo *getNmhlInfo(int hl)
2835 {
2836   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
2837   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
2838   static NmhlInfo nmhlInfo[] = 
2839   {
2840     NmhlInfo("namespacemembers",     theTranslator->trAll()),
2841     NmhlInfo("namespacemembers_func",
2842         fortranOpt ? theTranslator->trSubprograms()  :
2843         vhdlOpt    ? VhdlDocGen::trFunctionAndProc() :
2844                      theTranslator->trFunctions()),
2845     NmhlInfo("namespacemembers_vars",theTranslator->trVariables()),
2846     NmhlInfo("namespacemembers_type",theTranslator->trTypedefs()),
2847     NmhlInfo("namespacemembers_enum",theTranslator->trEnumerations()),
2848     NmhlInfo("namespacemembers_eval",theTranslator->trEnumerationValues())
2849   };
2850   return &nmhlInfo[hl];
2851 }
2852
2853 //----------------------------------------------------------------------------
2854
2855 static void writeNamespaceMemberIndexFiltered(OutputList &ol,
2856                                         NamespaceMemberHighlight hl)
2857 {
2858   if (documentedNamespaceMembers[hl]==0) return;
2859
2860   static bool disableIndex     = Config_getBool("DISABLE_INDEX");
2861
2862
2863   bool multiPageIndex=FALSE;
2864   if (documentedNamespaceMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
2865   {
2866     multiPageIndex=TRUE;
2867   }
2868
2869   ol.pushGeneratorState();
2870   ol.disableAllBut(OutputGenerator::Html);
2871
2872   QCString extension=Doxygen::htmlFileExtension;
2873   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceMembers);
2874   QCString title = lne ? lne->title() : theTranslator->trNamespaceMembers();
2875   bool addToIndex = lne==0 || lne->visible();
2876
2877   if (addToIndex)
2878   {
2879     Doxygen::indexList->addContentsItem(multiPageIndex,getNmhlInfo(hl)->title,0,
2880         getNmhlInfo(hl)->fname,0,multiPageIndex,TRUE);
2881     if (multiPageIndex) Doxygen::indexList->incContentsDepth();
2882   }
2883
2884   bool first=TRUE;
2885   SIntDict<MemberIndexList>::Iterator it(g_namespaceIndexLetterUsed[hl]);
2886   MemberIndexList *ml;
2887   for (it.toFirst();(ml=it.current());++it)
2888   {
2889     uint page = ml->letter();
2890     QCString fileName = getNmhlInfo(hl)->fname;
2891     if (multiPageIndex)
2892     {
2893       if (!first)
2894       {
2895         fileName+="_"+letterToLabel(page);
2896       }
2897       QCString cs = QString(QChar(page)).utf8();
2898       if (addToIndex)
2899       {
2900         Doxygen::indexList->addContentsItem(FALSE,cs,0,fileName,0,FALSE,TRUE);
2901       }
2902     }
2903     bool quickIndex = documentedNamespaceMembers[hl]>maxItemsBeforeQuickIndex;
2904
2905     ol.startFile(fileName+extension,0,title);
2906     ol.startQuickIndices();
2907     if (!disableIndex)
2908     {
2909       ol.writeQuickLinks(TRUE,HLI_NamespaceMembers,0);
2910       startQuickIndexList(ol);
2911
2912       // index item for all namespace member lists
2913       startQuickIndexItem(ol,
2914           getNmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==NMHL_All,TRUE,first);
2915       ol.writeString(fixSpaces(getNmhlInfo(0)->title));
2916       endQuickIndexItem(ol);
2917
2918       int i;
2919       // index items per category member lists
2920       for (i=1;i<NMHL_Total;i++)
2921       {
2922         if (documentedNamespaceMembers[i]>0)
2923         {
2924           startQuickIndexItem(ol,
2925               getNmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
2926           ol.writeString(fixSpaces(getNmhlInfo(i)->title));
2927           endQuickIndexItem(ol);
2928         }
2929       }
2930
2931       endQuickIndexList(ol);
2932
2933       if (quickIndex)
2934       {
2935         writeQuickMemberIndex(ol,g_namespaceIndexLetterUsed[hl],page,
2936             getNmhlInfo(hl)->fname,multiPageIndex);
2937       }
2938
2939     }
2940     ol.endQuickIndices();
2941     ol.writeSplitBar(fileName);
2942     ol.writeSearchInfo();
2943
2944     ol.startContents();
2945
2946     if (hl==NMHL_All)
2947     {
2948       ol.startTextBlock();
2949       ol.parseText(lne ? lne->intro() : theTranslator->trNamespaceMemberDescription(Config_getBool("EXTRACT_ALL")));
2950       ol.endTextBlock();
2951     }
2952     else
2953     {
2954       // hack to work around a mozilla bug, which refuses to switch to
2955       // normal lists otherwise
2956       ol.writeString("&#160;");
2957     }
2958
2959     writeMemberList(ol,quickIndex,
2960         multiPageIndex?page:-1,
2961         g_namespaceIndexLetterUsed[hl],
2962         Definition::TypeNamespace);
2963     endFile(ol);
2964   }
2965   if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
2966   ol.popGeneratorState();
2967 }
2968
2969 static void writeNamespaceMemberIndex(OutputList &ol)
2970 {
2971   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceMembers);
2972   bool addToIndex = lne==0 || lne->visible();
2973   if (documentedNamespaceMembers[NMHL_All]>0 && addToIndex)
2974   {
2975     Doxygen::indexList->addContentsItem(FALSE,lne ? lne->title() : theTranslator->trNamespaceMembers(),0,"namespacemembers",0); 
2976     Doxygen::indexList->incContentsDepth();
2977   }
2978   //bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
2979   writeNamespaceMemberIndexFiltered(ol,NMHL_All);
2980   writeNamespaceMemberIndexFiltered(ol,NMHL_Functions);
2981   writeNamespaceMemberIndexFiltered(ol,NMHL_Variables);
2982   writeNamespaceMemberIndexFiltered(ol,NMHL_Typedefs);
2983   writeNamespaceMemberIndexFiltered(ol,NMHL_Enums);
2984   writeNamespaceMemberIndexFiltered(ol,NMHL_EnumValues);
2985   if (documentedNamespaceMembers[NMHL_All]>0 && addToIndex)
2986   {
2987     Doxygen::indexList->decContentsDepth();
2988   }
2989
2990 }
2991
2992 //----------------------------------------------------------------------------
2993
2994 //----------------------------------------------------------------------------
2995
2996 static void writeExampleIndex(OutputList &ol)
2997 {
2998   if (Doxygen::exampleSDict->count()==0) return;
2999   ol.pushGeneratorState();
3000   ol.disable(OutputGenerator::Man);
3001   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Examples);
3002   QCString title = lne ? lne->title() : theTranslator->trExamples();
3003   bool addToIndex = lne==0 || lne->visible();
3004
3005   startFile(ol,"examples",0,title,HLI_Examples);
3006
3007   startTitle(ol,0);
3008   ol.parseText(title);
3009   endTitle(ol,0,0);
3010
3011   ol.startContents();
3012
3013   if (addToIndex)
3014   {
3015     Doxygen::indexList->addContentsItem(TRUE,title,0,"examples",0,TRUE,TRUE); 
3016     Doxygen::indexList->incContentsDepth();
3017   }
3018
3019   ol.startTextBlock();
3020   ol.parseText(lne ? lne->intro() : theTranslator->trExamplesDescription());
3021   ol.endTextBlock();
3022
3023   ol.startItemList();
3024   PageSDict::Iterator pdi(*Doxygen::exampleSDict);
3025   PageDef *pd=0;
3026   for (pdi.toFirst();(pd=pdi.current());++pdi)
3027   {
3028     ol.startItemListItem();
3029     QCString n=pd->getOutputFileBase();
3030     if (!pd->title().isEmpty())
3031     {
3032       ol.writeObjectLink(0,n,0,pd->title());
3033       if (addToIndex)
3034       {
3035         Doxygen::indexList->addContentsItem(FALSE,filterTitle(pd->title()),pd->getReference(),n,0,FALSE,TRUE);
3036       }
3037     }
3038     else
3039     {
3040       ol.writeObjectLink(0,n,0,pd->name());
3041       if (addToIndex)
3042       {
3043         Doxygen::indexList->addContentsItem(FALSE,pd->name(),pd->getReference(),n,0,FALSE,TRUE);
3044       }
3045     }
3046     ol.endItemListItem();
3047     ol.writeString("\n");
3048   }
3049   ol.endItemList();
3050
3051   if (addToIndex)
3052   {
3053     Doxygen::indexList->decContentsDepth();
3054   }
3055   endFile(ol);
3056   ol.popGeneratorState();
3057 }
3058
3059
3060 //----------------------------------------------------------------------------
3061
3062 static void countRelatedPages(int &docPages,int &indexPages)
3063 {
3064   docPages=indexPages=0;
3065   PageSDict::Iterator pdi(*Doxygen::pageSDict);
3066   PageDef *pd=0;
3067   for (pdi.toFirst();(pd=pdi.current());++pdi)
3068   {
3069     if ( pd->visibleInIndex())
3070     {
3071       indexPages++; 
3072     }
3073     if ( pd->documentedPage())
3074     {
3075       docPages++;
3076     }
3077   }
3078 }
3079
3080 //----------------------------------------------------------------------------
3081
3082 static void writePages(PageDef *pd,FTVHelp *ftv)
3083 {
3084   //printf("writePages()=%s pd=%p mainpage=%p\n",pd->name().data(),pd,Doxygen::mainPage);
3085   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Pages);
3086   bool addToIndex = lne==0 || lne->visible();
3087   if (!addToIndex) return;
3088
3089   bool hasSubPages = pd->hasSubPages();
3090   bool hasSections = pd->hasSections();
3091
3092   if (pd->visibleInIndex())
3093   {
3094     QCString pageTitle;
3095
3096     if (pd->title().isEmpty())
3097       pageTitle=pd->name();
3098     else
3099       pageTitle=filterTitle(pd->title());
3100
3101     if (ftv)
3102     {
3103       //printf("*** adding %s\n",pageTitle.data());
3104       ftv->addContentsItem(
3105           hasSubPages,pageTitle,
3106           pd->getReference(),pd->getOutputFileBase(),
3107           0,hasSubPages,TRUE,pd); 
3108     }
3109     if (addToIndex && pd!=Doxygen::mainPage)
3110     {
3111       Doxygen::indexList->addContentsItem(
3112           hasSubPages,pageTitle,
3113           pd->getReference(),pd->getOutputFileBase(),
3114           0,hasSubPages,TRUE);
3115     }
3116   }
3117   if (hasSubPages && ftv) ftv->incContentsDepth();
3118   bool doIndent = (hasSections || hasSubPages) &&  
3119                   (pd!=Doxygen::mainPage || mainPageHasTitle());
3120   if (doIndent)
3121   {
3122     Doxygen::indexList->incContentsDepth();
3123   }
3124   if (hasSections)
3125   {
3126     pd->addSectionsToIndex();
3127   }
3128   PageSDict *subPages = pd->getSubPages();
3129   if (subPages)
3130   {
3131     PageSDict::Iterator pi(*subPages);
3132     PageDef *subPage;
3133     for (pi.toFirst();(subPage=pi.current());++pi)
3134     {
3135       writePages(subPage,ftv);
3136     }
3137   }
3138   if (hasSubPages && ftv) ftv->decContentsDepth();
3139   if (doIndent)
3140   {
3141     Doxygen::indexList->decContentsDepth();
3142   }
3143   //printf("end writePages()=%s\n",pd->title().data());
3144 }
3145
3146 //----------------------------------------------------------------------------
3147
3148 static void writePageIndex(OutputList &ol)
3149 {
3150   if (indexedPages==0) return;
3151   ol.pushGeneratorState();
3152   ol.disableAllBut(OutputGenerator::Html);
3153   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Pages);
3154   QCString title = lne ? lne->title() : theTranslator->trRelatedPages();
3155   startFile(ol,"pages",0,title,HLI_Pages);
3156   startTitle(ol,0);
3157   ol.parseText(title);
3158   endTitle(ol,0,0);
3159   ol.startContents();
3160   ol.startTextBlock();
3161   ol.parseText(lne ? lne->intro() : theTranslator->trRelatedPagesDescription());
3162   ol.endTextBlock();
3163
3164   {
3165     FTVHelp* ftv = new FTVHelp(FALSE);
3166     PageSDict::Iterator pdi(*Doxygen::pageSDict);
3167     PageDef *pd=0;
3168     for (pdi.toFirst();(pd=pdi.current());++pdi)
3169     {
3170       if ((pd->getOuterScope()==0 ||
3171           pd->getOuterScope()->definitionType()!=Definition::TypePage) && // not a sub page
3172           !pd->isReference() // not an external page
3173          )
3174       {
3175         writePages(pd,ftv);
3176       }
3177     }
3178     QGString outStr;
3179     FTextStream t(&outStr);
3180     ftv->generateTreeViewInline(t);
3181     ol.writeString(outStr);
3182     delete ftv;
3183   }
3184
3185 //  ol.popGeneratorState();
3186   // ------
3187
3188   endFile(ol);
3189   ol.popGeneratorState();
3190 }
3191
3192 //----------------------------------------------------------------------------
3193
3194 static int countGroups()
3195 {
3196   int count=0;
3197   GroupSDict::Iterator gli(*Doxygen::groupSDict);
3198   GroupDef *gd;
3199   for (gli.toFirst();(gd=gli.current());++gli)
3200   {
3201     if (!gd->isReference())
3202     {
3203       gd->visited=FALSE;
3204       count++;
3205     }
3206   }
3207   return count;
3208 }
3209
3210 //----------------------------------------------------------------------------
3211
3212 static int countDirs()
3213 {
3214   int count=0;
3215   SDict<DirDef>::Iterator dli(*Doxygen::directories);
3216   DirDef *dd;
3217   for (dli.toFirst();(dd=dli.current());++dli)
3218   {
3219     if (dd->isLinkableInProject())
3220     {
3221       dd->visited=FALSE;
3222       count++;
3223     }
3224   }
3225   return count;
3226 }
3227
3228
3229 //----------------------------------------------------------------------------
3230
3231 void writeGraphInfo(OutputList &ol)
3232 {
3233   if (!Config_getBool("HAVE_DOT") || !Config_getBool("GENERATE_HTML")) return;
3234   ol.pushGeneratorState();
3235   ol.disableAllBut(OutputGenerator::Html);
3236   generateGraphLegend(Config_getString("HTML_OUTPUT"));
3237
3238   bool &stripCommentsStateRef = Config_getBool("STRIP_CODE_COMMENTS");
3239   bool oldStripCommentsState = stripCommentsStateRef;
3240   bool &createSubdirs = Config_getBool("CREATE_SUBDIRS");
3241   bool oldCreateSubdirs = createSubdirs;
3242   // temporarily disable the stripping of comments for our own code example!
3243   stripCommentsStateRef = FALSE;
3244   // temporarily disable create subdirs for linking to our example
3245   createSubdirs = FALSE;
3246
3247   startFile(ol,"graph_legend",0,theTranslator->trLegendTitle().data());
3248   startTitle(ol,0);
3249   ol.parseText(theTranslator->trLegendTitle());
3250   endTitle(ol,0,0);
3251   ol.startContents();
3252   QCString legendDocs = theTranslator->trLegendDocs();
3253   int s = legendDocs.find("<center>");
3254   int e = legendDocs.find("</center>");
3255   if (Config_getEnum("DOT_IMAGE_FORMAT")=="svg" && s!=-1 && e!=-1)
3256   {
3257     legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e); 
3258     //printf("legendDocs=%s\n",legendDocs.data());
3259   }
3260   FileDef fd("","graph_legend");
3261   ol.generateDoc("graph_legend",1,&fd,0,legendDocs,FALSE,FALSE);
3262
3263   // restore config settings
3264   stripCommentsStateRef = oldStripCommentsState;
3265   createSubdirs = oldCreateSubdirs;
3266
3267   endFile(ol);
3268   ol.popGeneratorState();
3269 }
3270
3271
3272
3273 //----------------------------------------------------------------------------
3274 /*!
3275  * write groups as hierarchical trees
3276  */
3277 static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* ftv, bool addToIndex)
3278 {
3279   //bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
3280   //bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");  
3281   if (level>20)
3282   {
3283     warn(gd->getDefFileName(),gd->getDefLine(),
3284         "maximum nesting level exceeded for group %s: check for possible recursive group relation!\n",gd->name().data()
3285         );
3286     return;
3287   }
3288
3289   /* Some groups should appear twice under different parent-groups.
3290    * That is why we should not check if it was visited 
3291    */
3292   if (/*!gd->visited &&*/ (!gd->isASubGroup() || level>0) &&
3293       gd->isVisible() &&
3294       (!gd->isReference() || Config_getBool("EXTERNAL_GROUPS")) // hide external groups by default
3295      )
3296   {
3297     //printf("gd->name()=%s #members=%d\n",gd->name().data(),gd->countMembers());
3298     // write group info
3299     bool hasSubGroups = gd->getSubGroups()->count()>0;
3300     bool hasSubPages = gd->getPages()->count()>0;
3301     int numSubItems = 0;
3302     if (1 /*Config_getBool("TOC_EXPAND")*/)
3303     {
3304       QListIterator<MemberList> mli(gd->getMemberLists());
3305       MemberList *ml;
3306       for (mli.toFirst();(ml=mli.current());++mli)
3307       {
3308         if (ml->listType()&MemberListType_documentationLists)
3309         {
3310           numSubItems += ml->count();
3311         }
3312       }
3313       numSubItems += gd->getNamespaces()->count();
3314       numSubItems += gd->getClasses()->count();
3315       numSubItems += gd->getFiles()->count();
3316       numSubItems += gd->getDirs()->count();
3317       numSubItems += gd->getPages()->count();
3318     }
3319
3320     bool isDir = hasSubGroups || hasSubPages || numSubItems>0;
3321     //printf("gd=`%s': pageDict=%d\n",gd->name().data(),gd->pageDict->count());
3322     if (addToIndex)
3323     {
3324       Doxygen::indexList->addContentsItem(isDir,gd->groupTitle(),gd->getReference(),gd->getOutputFileBase(),0,isDir,TRUE); 
3325       Doxygen::indexList->incContentsDepth();
3326     }
3327     if (ftv)
3328     {
3329       ftv->addContentsItem(hasSubGroups,gd->groupTitle(),
3330                            gd->getReference(),gd->getOutputFileBase(),0,
3331                            FALSE,FALSE,gd); 
3332       ftv->incContentsDepth();
3333     }
3334     
3335     //ol.writeListItem();
3336     //ol.startTextLink(gd->getOutputFileBase(),0);
3337     //parseText(ol,gd->groupTitle());
3338     //ol.endTextLink();
3339
3340     ol.startIndexListItem();
3341     ol.startIndexItem(gd->getReference(),gd->getOutputFileBase());
3342     ol.parseText(gd->groupTitle());
3343     ol.endIndexItem(gd->getReference(),gd->getOutputFileBase());
3344     if (gd->isReference()) 
3345     { 
3346       ol.startTypewriter(); 
3347       ol.docify(" [external]");
3348       ol.endTypewriter();
3349     }
3350
3351     QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(LayoutDocManager::Group));
3352     LayoutDocEntry *lde;
3353     for (eli.toFirst();(lde=eli.current());++eli)
3354     {
3355       if (lde->kind()==LayoutDocEntry::MemberDef && addToIndex)
3356       {
3357         LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde;
3358         MemberList *ml = gd->getMemberList(lmd->type);
3359         if (ml)
3360         {
3361           MemberListIterator mi(*ml);
3362           MemberDef *md;
3363           for (mi.toFirst();(md=mi.current());++mi)
3364           {
3365             MemberList *enumList = md->enumFieldList();
3366             bool isDir = enumList!=0 && md->isEnumerate();
3367             if (md->isVisible() && md->name().find('@')==-1)
3368             {
3369               Doxygen::indexList->addContentsItem(isDir,
3370                   md->name(),md->getReference(),
3371                   md->getOutputFileBase(),md->anchor(),FALSE,addToIndex);
3372             }
3373             if (isDir)
3374             {
3375               Doxygen::indexList->incContentsDepth();
3376               MemberListIterator emli(*enumList);
3377               MemberDef *emd;
3378               for (emli.toFirst();(emd=emli.current());++emli)
3379               {
3380                 if (emd->isVisible())
3381                 {
3382                   Doxygen::indexList->addContentsItem(FALSE,
3383                       emd->name(),emd->getReference(),emd->getOutputFileBase(),
3384                       emd->anchor(),FALSE,addToIndex);
3385                 }
3386               }
3387               Doxygen::indexList->decContentsDepth();
3388             }
3389           }
3390         }
3391       }
3392       else if (lde->kind()==LayoutDocEntry::GroupClasses && addToIndex)
3393       {
3394         ClassSDict::Iterator it(*gd->getClasses());
3395         ClassDef *cd;
3396         for (;(cd=it.current());++it)
3397         {
3398           //bool nestedClassInSameGroup = 
3399           //    cd->getOuterScope() && cd->getOuterScope()->definitionType()==Definition::TypeClass &&
3400           //    cd->getOuterScope()->partOfGroups()!=0 && cd->getOuterScope()->partOfGroups()->contains(gd);
3401           //printf("===== GroupClasses: %s visible=%d nestedClassInSameGroup=%d\n",cd->name().data(),cd->isVisible(),nestedClassInSameGroup);
3402           if (cd->isVisible() /*&& !nestedClassInSameGroup*/)
3403           {
3404             //if (cd->isEmbeddedInOuterScope())
3405             //{
3406               //printf("add class & members %d\n",addToIndex);
3407               addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(),addToIndex,TRUE);
3408             //}
3409             //else // only index the class, not its members
3410             //{
3411             //  printf("%s: add class only\n",cd->name().data());
3412             //  Doxygen::indexList->addContentsItem(FALSE,
3413             //    cd->displayName(TRUE),cd->getReference(),
3414             //    cd->getOutputFileBase(),cd->anchor(),addToIndex,TRUE);
3415             //}
3416           }
3417         }
3418       }
3419       else if (lde->kind()==LayoutDocEntry::GroupNamespaces && addToIndex)
3420       {
3421         NamespaceSDict::Iterator it(*gd->getNamespaces());
3422         NamespaceDef *nd;
3423         for (;(nd=it.current());++it)
3424         {
3425           if (nd->isVisible())
3426           {
3427             Doxygen::indexList->addContentsItem(FALSE,
3428                 nd->localName(),nd->getReference(),
3429                 nd->getOutputFileBase(),0,FALSE,FALSE);
3430           }
3431         }
3432       }
3433       else if (lde->kind()==LayoutDocEntry::GroupFiles && addToIndex)
3434       {
3435         QListIterator<FileDef> it(*gd->getFiles());
3436         FileDef *fd;
3437         for (;(fd=it.current());++it)
3438         {
3439           if (fd->isVisible())
3440           {
3441             Doxygen::indexList->addContentsItem(FALSE,
3442                 fd->displayName(),fd->getReference(),
3443                 fd->getOutputFileBase(),0,FALSE,FALSE);
3444           }
3445         }
3446       }
3447       else if (lde->kind()==LayoutDocEntry::GroupDirs && addToIndex)
3448       {
3449         QListIterator<DirDef> it(*gd->getDirs());
3450         DirDef *dd;
3451         for (;(dd=it.current());++it)
3452         {
3453           if (dd->isVisible())
3454           {
3455             Doxygen::indexList->addContentsItem(FALSE,
3456                 dd->shortName(),dd->getReference(),
3457                 dd->getOutputFileBase(),0,FALSE,FALSE);
3458           }
3459         }
3460       }
3461       else if (lde->kind()==LayoutDocEntry::GroupPageDocs && addToIndex)
3462       {
3463         SDict<PageDef>::Iterator it(*gd->getPages());
3464         PageDef *pd;
3465         for (;(pd=it.current());++it)
3466         {
3467           SectionInfo *si=0;
3468           if (!pd->name().isEmpty()) si=Doxygen::sectionDict->find(pd->name());
3469           bool hasSubPages = pd->hasSubPages();
3470           bool hasSections = pd->hasSections();
3471           Doxygen::indexList->addContentsItem(
3472               hasSubPages || hasSections,
3473               convertToHtml(pd->title(),TRUE),
3474               gd->getReference(),
3475               gd->getOutputFileBase(),
3476               si ? si->label.data() : 0,
3477               hasSubPages || hasSections,
3478               TRUE); // addToNavIndex
3479           if (hasSections || hasSubPages)
3480           {
3481             Doxygen::indexList->incContentsDepth();
3482           }
3483           if (hasSections)
3484           {
3485             pd->addSectionsToIndex();
3486           }
3487           writePages(pd,0);
3488           if (hasSections || hasSubPages)
3489           {
3490             Doxygen::indexList->decContentsDepth();
3491           }
3492         }
3493       }
3494       else if (lde->kind()==LayoutDocEntry::GroupNestedGroups)
3495       {
3496         if (gd->getSubGroups()->count()>0)
3497         {
3498           startIndexHierarchy(ol,level+1);
3499           QListIterator<GroupDef> gli(*gd->getSubGroups());
3500           GroupDef *subgd = 0;
3501           for (gli.toFirst();(subgd=gli.current());++gli)
3502           {
3503             writeGroupTreeNode(ol,subgd,level+1,ftv,addToIndex);
3504           }
3505           endIndexHierarchy(ol,level+1); 
3506         }
3507       }
3508     }
3509
3510     ol.endIndexListItem();
3511     
3512     if (addToIndex)
3513     {
3514       Doxygen::indexList->decContentsDepth();
3515     }
3516     if (ftv)
3517     {
3518       ftv->decContentsDepth();
3519     }
3520     //gd->visited=TRUE;
3521   }
3522 }
3523
3524 static void writeGroupHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
3525 {
3526   if (ftv)
3527   {
3528     ol.pushGeneratorState(); 
3529     ol.disable(OutputGenerator::Html);
3530   }
3531   startIndexHierarchy(ol,0);
3532   GroupSDict::Iterator gli(*Doxygen::groupSDict);
3533   GroupDef *gd;
3534   for (gli.toFirst();(gd=gli.current());++gli)
3535   {
3536     writeGroupTreeNode(ol,gd,0,ftv,addToIndex);
3537   }
3538   endIndexHierarchy(ol,0); 
3539   if (ftv)
3540   {
3541     ol.popGeneratorState(); 
3542   }
3543 }
3544
3545 #if 0
3546 static void writeGroupTree(GroupDef *gd,FTVHelp *ftv,int level,bool addToIndex)
3547 {
3548   static bool externalGroups = Config_getBool("EXTERNAL_GROUPS");
3549   /* Some groups should appear twice under different parent-groups.
3550    * That is why we should not check if it was visited 
3551    */
3552   if ((!gd->isASubGroup() || level>0) &&
3553       gd->isVisible() &&
3554       (!gd->isReference() || externalGroups) // hide external groups by default
3555      )
3556   {
3557     if (ftv)
3558     {
3559       ftv->addContentsItem(hasSubGroups,gd->groupTitle(),gd->getReference(),gd->getOutputFileBase(),0); 
3560       ftv->incContentsDepth();
3561     }
3562     if (ftv)
3563     {
3564       ftv->decContentsDepth();
3565     }
3566   }
3567 }
3568
3569 static void writeGroupTree(FTVHelp *ftv,bool addToIndex)
3570 {
3571   GroupSDict::Iterator gli(*Doxygen::groupSDict);
3572   GroupDef *gd;
3573   for (gli.toFirst();(gd=gli.current());++gli)
3574   {
3575     writeGroupTree(gd,ftv,0,addToIndex);
3576   }
3577 }
3578 #endif
3579
3580 //----------------------------------------------------------------------------
3581
3582 static void writeGroupIndex(OutputList &ol)
3583 {
3584   if (documentedGroups==0) return; 
3585   ol.pushGeneratorState(); 
3586   // 1.{
3587   ol.disable(OutputGenerator::Man);
3588   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Modules);
3589   QCString title = lne ? lne->title() : theTranslator->trModules();
3590   bool addToIndex = lne==0 || lne->visible();
3591
3592   startFile(ol,"modules",0,title,HLI_Modules);
3593   startTitle(ol,0);
3594   ol.parseText(title);
3595   endTitle(ol,0,0);
3596   ol.startContents();
3597   ol.startTextBlock();
3598   ol.parseText(lne ? lne->intro() : theTranslator->trModulesDescription());
3599   ol.endTextBlock();
3600
3601   // ---------------
3602   // Normal group index for Latex/RTF
3603   // ---------------
3604   // 2.{
3605   ol.pushGeneratorState();
3606   ol.disable(OutputGenerator::Html);
3607   Doxygen::indexList->disable();
3608
3609   writeGroupHierarchy(ol,0,FALSE);
3610
3611   Doxygen::indexList->enable();
3612   ol.popGeneratorState();
3613   // 2.}
3614
3615   // ---------------
3616   // interactive group index for HTML
3617   // ---------------
3618   // 2.{
3619   ol.pushGeneratorState(); 
3620   ol.disableAllBut(OutputGenerator::Html);
3621
3622   {
3623     if (addToIndex)
3624     {
3625       Doxygen::indexList->addContentsItem(TRUE,title,0,"modules",0,TRUE,TRUE); 
3626       Doxygen::indexList->incContentsDepth();
3627     }
3628     FTVHelp* ftv = new FTVHelp(FALSE);
3629     writeGroupHierarchy(ol,ftv,addToIndex);
3630     QGString outStr;
3631     FTextStream t(&outStr);
3632     ftv->generateTreeViewInline(t);
3633     ol.disableAllBut(OutputGenerator::Html);
3634     ol.writeString(outStr);
3635     delete ftv;
3636     if (addToIndex)
3637     {
3638       Doxygen::indexList->decContentsDepth();
3639     }
3640   }
3641   ol.popGeneratorState();
3642   // 2.}
3643
3644   endFile(ol);
3645   ol.popGeneratorState();
3646   // 1.}
3647 }
3648
3649 //----------------------------------------------------------------------------
3650
3651 #if 0
3652 static void writeDirIndex(OutputList &ol)
3653 {
3654   if (documentedDirs==0) return; 
3655   ol.pushGeneratorState(); 
3656   ol.disable(OutputGenerator::Man);
3657   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Dirs);
3658   QCString title = lne ? lne->title() : theTranslator->trDirectories();
3659   bool addToIndex=FALSE; //lne==0 || lne->visible();
3660
3661   startFile(ol,"dirs",0,title,HLI_Directories);
3662   startTitle(ol,0);
3663   ol.parseText(title);
3664   endTitle(ol,0,0);
3665   ol.startContents();
3666   ol.startTextBlock();
3667
3668   if (addToIndex)
3669   {
3670     Doxygen::indexList->addContentsItem(TRUE,title,0,"dirs",0,TRUE,TRUE); 
3671     Doxygen::indexList->incContentsDepth();
3672   }
3673   ol.parseText(lne ? lne->intro() : theTranslator->trDirDescription());
3674   ol.endTextBlock();
3675
3676   FTVHelp* ftv = 0;
3677   bool treeView=Config_getBool("USE_INLINE_TREES");
3678   if (treeView)
3679   {
3680     ftv = new FTVHelp(FALSE);
3681   }
3682
3683   writeDirHierarchy(ol,ftv,addToIndex);
3684
3685   if (ftv)
3686   {
3687     QGString outStr;
3688     FTextStream t(&outStr);
3689     ftv->generateTreeViewInline(t);
3690     ol.pushGeneratorState(); 
3691     ol.disableAllBut(OutputGenerator::Html);
3692     ol.writeString(outStr);
3693     ol.popGeneratorState();
3694     delete ftv;
3695   }
3696   if (addToIndex)
3697   {
3698     Doxygen::indexList->decContentsDepth();
3699   }
3700   endFile(ol);
3701   ol.popGeneratorState();
3702 }
3703 #endif
3704
3705 //----------------------------------------------------------------------------
3706
3707 static void writeUserGroupStubPage(OutputList &ol,LayoutNavEntry *lne)
3708 {
3709   if (lne->baseFile().left(9)=="usergroup")
3710   {
3711     ol.pushGeneratorState();
3712     ol.disableAllBut(OutputGenerator::Html);
3713     startFile(ol,lne->baseFile(),0,lne->title(),HLI_UserGroup);
3714     startTitle(ol,0);
3715     ol.parseText(lne->title());
3716     endTitle(ol,0,0);
3717     ol.startContents();
3718     QListIterator<LayoutNavEntry> li(lne->children());
3719     LayoutNavEntry *entry;
3720     int count=0;
3721     for (li.toFirst();(entry=li.current());++li)
3722     {
3723       if (entry->visible()) count++;
3724     }
3725     if (count>0)
3726     {
3727       ol.writeString("<ul>\n");
3728       for (li.toFirst();(entry=li.current());++li)
3729       {
3730         if (entry->visible())
3731         {
3732           ol.writeString("<li><a href=\""+entry->url()+"\"><span>"+
3733               fixSpaces(entry->title())+"</span></a></li>\n");
3734         }
3735       }
3736       ol.writeString("</ul>\n");
3737     }
3738     endFile(ol);
3739     ol.popGeneratorState();
3740   }
3741 }
3742
3743 //----------------------------------------------------------------------------
3744
3745
3746 static void writeIndex(OutputList &ol)
3747 {
3748   static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
3749   static bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");
3750   static QCString projectName = Config_getString("PROJECT_NAME");
3751   // save old generator state
3752   ol.pushGeneratorState();
3753
3754   QCString projPrefix;
3755   if (!projectName.isEmpty())
3756   {
3757     projPrefix=projectName+" ";
3758   }
3759
3760   //--------------------------------------------------------------------
3761   // write HTML index
3762   //--------------------------------------------------------------------
3763   ol.disableAllBut(OutputGenerator::Html);
3764
3765   QCString defFileName = 
3766     Doxygen::mainPage ? Doxygen::mainPage->docFile().data() : "[generated]";
3767   int defLine =
3768     Doxygen::mainPage ? Doxygen::mainPage->docLine() : -1;
3769
3770   QCString title;
3771   if (!mainPageHasTitle())
3772   {
3773     title = theTranslator->trMainPage();
3774   }
3775   else 
3776   {
3777     title = filterTitle(Doxygen::mainPage->title());
3778   }
3779
3780   QCString indexName="index";
3781   ol.startFile(indexName,0,title);
3782   
3783   if (Doxygen::mainPage)
3784   {
3785     if (
3786         (!projectName.isEmpty() && mainPageHasTitle() && qstricmp(title,projectName)!=0)
3787        ) // to avoid duplicate entries in the treeview
3788     {
3789       Doxygen::indexList->addContentsItem(Doxygen::mainPage->hasSubPages(),title,0,indexName,0,Doxygen::mainPage->hasSubPages(),TRUE); 
3790     }
3791     if (Doxygen::mainPage->hasSubPages() || Doxygen::mainPage->hasSections())
3792     {
3793       writePages(Doxygen::mainPage,0);
3794     }
3795   }
3796
3797   ol.startQuickIndices();
3798   if (!Config_getBool("DISABLE_INDEX")) 
3799   {
3800     ol.writeQuickLinks(TRUE,HLI_Main,0);
3801   }
3802   ol.endQuickIndices();
3803   ol.writeSplitBar(indexName);
3804   ol.writeSearchInfo();
3805   bool headerWritten=FALSE;
3806   if (Doxygen::mainPage && !Doxygen::mainPage->title().isEmpty())
3807   {
3808     if (Doxygen::mainPage->title().lower()!="notitle")
3809     {
3810       ol.startHeaderSection();
3811       ol.startTitleHead(0);
3812       ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->docLine(),
3813                   Doxygen::mainPage,0,Doxygen::mainPage->title(),
3814                   TRUE,FALSE,0,TRUE,FALSE);
3815       headerWritten = TRUE;
3816     }
3817   }
3818   else
3819   {
3820     if (!projectName.isEmpty())
3821     {
3822       ol.startHeaderSection();
3823       ol.startTitleHead(0);
3824       ol.parseText(projPrefix+theTranslator->trDocumentation());
3825       headerWritten = TRUE;
3826     }
3827   }
3828   if (headerWritten)
3829   {
3830     ol.endTitleHead(0,0);
3831     ol.endHeaderSection();
3832   }
3833
3834   ol.startContents();
3835   if (Config_getBool("DISABLE_INDEX") && Doxygen::mainPage==0) 
3836   {
3837     ol.writeQuickLinks(FALSE,HLI_Main,0);
3838   }
3839
3840   if (Doxygen::mainPage)
3841   {
3842     Doxygen::insideMainPage=TRUE;
3843     if (Doxygen::mainPage->showToc() && Doxygen::mainPage->hasSections())
3844     {
3845       Doxygen::mainPage->writeToc(ol);
3846     }
3847
3848     ol.startTextBlock();
3849     ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,
3850                 Doxygen::mainPage->documentation(),TRUE,FALSE
3851                 /*,Doxygen::mainPage->sectionDict*/);
3852     ol.endTextBlock();
3853
3854     Doxygen::insideMainPage=FALSE;
3855   }
3856   
3857   endFile(ol);
3858   ol.disable(OutputGenerator::Html);
3859   
3860   //--------------------------------------------------------------------
3861   // write LaTeX/RTF index
3862   //--------------------------------------------------------------------
3863   ol.enable(OutputGenerator::Latex);
3864   ol.enable(OutputGenerator::RTF);
3865
3866   ol.startFile("refman",0,0);
3867   ol.startIndexSection(isTitlePageStart);
3868   if (!Config_getString("LATEX_HEADER").isEmpty()) 
3869   {
3870     ol.disable(OutputGenerator::Latex);
3871   }
3872
3873   if (projPrefix.isEmpty())
3874   {
3875     ol.parseText(theTranslator->trReferenceManual());
3876   }
3877   else
3878   {
3879     ol.parseText(projPrefix);
3880   }
3881
3882   if (!Config_getString("PROJECT_NUMBER").isEmpty())
3883   {
3884     ol.startProjectNumber(); 
3885     ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,Config_getString("PROJECT_NUMBER"),FALSE,FALSE);
3886     ol.endProjectNumber();
3887   }
3888   ol.endIndexSection(isTitlePageStart);
3889   ol.startIndexSection(isTitlePageAuthor);
3890   ol.parseText(theTranslator->trGeneratedBy());
3891   ol.endIndexSection(isTitlePageAuthor);
3892   ol.enable(OutputGenerator::Latex);
3893
3894   ol.lastIndexPage();
3895   if (Doxygen::mainPage)
3896   {
3897     ol.startIndexSection(isMainPage);
3898     if (mainPageHasTitle())
3899     {
3900       ol.parseText(Doxygen::mainPage->title());
3901     }
3902     else
3903     {
3904       ol.parseText(/*projPrefix+*/theTranslator->trMainPage());
3905     }
3906     ol.endIndexSection(isMainPage);
3907   }
3908   if (documentedPages>0)
3909   {
3910     //ol.parseText(projPrefix+theTranslator->trPageDocumentation());
3911     //ol.endIndexSection(isPageDocumentation);
3912     PageSDict::Iterator pdi(*Doxygen::pageSDict);
3913     PageDef *pd=pdi.toFirst();
3914     bool first=Doxygen::mainPage==0;
3915     for (pdi.toFirst();(pd=pdi.current());++pdi)
3916     {
3917       if (!pd->getGroupDef() && !pd->isReference() && 
3918           (!pd->hasParentPage() ||                    // not inside other page
3919            (Doxygen::mainPage==pd->getOuterScope()))  // or inside main page
3920          )
3921       {
3922         bool isCitationPage = pd->name()=="citelist";
3923         if (isCitationPage)
3924         {
3925           // For LaTeX the bibliograph is already written by \bibliography
3926           ol.pushGeneratorState();
3927           ol.disable(OutputGenerator::Latex);
3928         }
3929         QCString title = pd->title();
3930         if (title.isEmpty()) title=pd->name();
3931
3932         ol.startIndexSection(isPageDocumentation);
3933         ol.parseText(title);
3934         ol.endIndexSection(isPageDocumentation);
3935
3936         ol.pushGeneratorState(); // write TOC title (RTF only)
3937           ol.disableAllBut(OutputGenerator::RTF);
3938           ol.startIndexSection(isPageDocumentation2);
3939           ol.parseText(title);
3940           ol.endIndexSection(isPageDocumentation2);
3941         ol.popGeneratorState();
3942
3943         ol.writeAnchor(0,pd->getOutputFileBase());
3944
3945         ol.writePageLink(pd->getOutputFileBase(),first);
3946         first=FALSE;
3947
3948         if (isCitationPage)
3949         {
3950           ol.popGeneratorState();
3951         }
3952       }
3953     }
3954   }
3955
3956   if (!Config_getBool("LATEX_HIDE_INDICES"))
3957   {
3958     //if (indexedPages>0)
3959     //{
3960     //  ol.startIndexSection(isPageIndex);
3961     //  ol.parseText(/*projPrefix+*/ theTranslator->trPageIndex());
3962     //  ol.endIndexSection(isPageIndex);
3963     //}
3964     if (documentedGroups>0)
3965     {
3966       ol.startIndexSection(isModuleIndex);
3967       ol.parseText(/*projPrefix+*/ theTranslator->trModuleIndex());
3968       ol.endIndexSection(isModuleIndex);
3969     }
3970     if (documentedNamespaces>0)
3971     {
3972       ol.startIndexSection(isNamespaceIndex);
3973       ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModulesIndex():theTranslator->trNamespaceIndex()));
3974       ol.endIndexSection(isNamespaceIndex);
3975     }
3976     if (hierarchyClasses>0)
3977     {
3978       ol.startIndexSection(isClassHierarchyIndex);
3979       ol.parseText(/*projPrefix+*/
3980           (fortranOpt ? theTranslator->trCompoundIndexFortran() : 
3981            vhdlOpt    ? VhdlDocGen::trDesignUnitIndex()         :
3982                         theTranslator->trHierarchicalIndex()
3983           ));
3984       ol.endIndexSection(isClassHierarchyIndex);
3985     }
3986     if (annotatedClassesPrinted>0)
3987     {
3988       ol.startIndexSection(isCompoundIndex);
3989       ol.parseText(/*projPrefix+*/
3990           (fortranOpt ? theTranslator->trCompoundIndexFortran() :
3991               vhdlOpt ? VhdlDocGen::trDesignUnitIndex()         : 
3992                         theTranslator->trCompoundIndex()
3993           ));
3994       ol.endIndexSection(isCompoundIndex);
3995     }
3996     if (documentedFiles>0)
3997     {
3998       ol.startIndexSection(isFileIndex);
3999       ol.parseText(/*projPrefix+*/theTranslator->trFileIndex());
4000       ol.endIndexSection(isFileIndex);
4001     }
4002   }
4003   if (documentedGroups>0)
4004   {
4005     ol.startIndexSection(isModuleDocumentation);
4006     ol.parseText(/*projPrefix+*/theTranslator->trModuleDocumentation());
4007     ol.endIndexSection(isModuleDocumentation);
4008   }
4009   if (documentedNamespaces>0)
4010   {
4011     ol.startIndexSection(isNamespaceDocumentation);
4012     ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModuleDocumentation():theTranslator->trNamespaceDocumentation()));
4013     ol.endIndexSection(isNamespaceDocumentation);
4014   }
4015   if (annotatedClassesPrinted>0)
4016   {
4017     ol.startIndexSection(isClassDocumentation);
4018     ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trTypeDocumentation():theTranslator->trClassDocumentation()));
4019     ol.endIndexSection(isClassDocumentation);
4020   }
4021   if (documentedFiles>0)
4022   {
4023     ol.startIndexSection(isFileDocumentation);
4024     ol.parseText(/*projPrefix+*/theTranslator->trFileDocumentation());
4025     ol.endIndexSection(isFileDocumentation);
4026   }
4027   if (Doxygen::exampleSDict->count()>0)
4028   {
4029     ol.startIndexSection(isExampleDocumentation);
4030     ol.parseText(/*projPrefix+*/theTranslator->trExampleDocumentation());
4031     ol.endIndexSection(isExampleDocumentation);
4032   }
4033   ol.endIndexSection(isEndIndex);
4034   endFile(ol);
4035
4036   if (Doxygen::mainPage)
4037   {
4038     Doxygen::insideMainPage=TRUE;
4039     ol.disable(OutputGenerator::Man);
4040     startFile(ol,Doxygen::mainPage->name(),0,Doxygen::mainPage->title());
4041     ol.startContents();
4042     ol.startTextBlock();
4043     ol.generateDoc(defFileName,defLine,Doxygen::mainPage,0,
4044                 Doxygen::mainPage->documentation(),FALSE,FALSE
4045                );
4046     ol.endTextBlock();
4047     endFile(ol);
4048     ol.enable(OutputGenerator::Man);
4049     Doxygen::insideMainPage=FALSE;
4050   }
4051
4052   ol.popGeneratorState();
4053 }
4054
4055 static QArray<bool> indexWritten;
4056
4057 static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry> &entries)
4058 {
4059   QListIterator<LayoutNavEntry> li(entries);
4060   LayoutNavEntry *lne;
4061   for (li.toFirst();(lne=li.current());++li)
4062   {
4063     LayoutNavEntry::Kind kind = lne->kind();
4064     uint index = (uint)kind;
4065     if (index>=indexWritten.size())
4066     {
4067       uint i;
4068       uint oldSize = indexWritten.size();
4069       uint newSize = index+1;
4070       indexWritten.resize(newSize);
4071       for (i=oldSize;i<newSize;i++) indexWritten.at(i)=FALSE;
4072     }
4073     //printf("starting %s kind=%d\n",lne->title().data(),lne->kind());
4074     bool addToIndex=lne==0 || lne->visible();
4075     bool needsClosing=FALSE;
4076     if (!indexWritten.at(index))
4077     {
4078       switch(kind)
4079       {
4080         case LayoutNavEntry::MainPage: 
4081           msg("Generating index page...\n");
4082           writeIndex(ol); 
4083           break;
4084         case LayoutNavEntry::Pages: 
4085           msg("Generating page index...\n");
4086           writePageIndex(ol);
4087           break;
4088         case LayoutNavEntry::Modules: 
4089           msg("Generating module index...\n");
4090           writeGroupIndex(ol);
4091           break;
4092         case LayoutNavEntry::Namespaces: 
4093           {
4094             static bool showNamespaces = Config_getBool("SHOW_NAMESPACES");
4095             if (showNamespaces)
4096             {
4097               if (documentedNamespaces>0 && addToIndex)
4098               {
4099                 Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0); 
4100                 Doxygen::indexList->incContentsDepth();
4101                 needsClosing=TRUE;
4102               }
4103               if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Namespaces)!=lne) // for backward compatibility with old layout file
4104               {
4105                 msg("Generating namespace index...\n");
4106                 writeNamespaceIndex(ol);
4107               }
4108             }
4109           }
4110           break;
4111         case LayoutNavEntry::NamespaceList: 
4112           {
4113             static bool showNamespaces = Config_getBool("SHOW_NAMESPACES");
4114             if (showNamespaces)
4115             {
4116               msg("Generating namespace index...\n");
4117               writeNamespaceIndex(ol);
4118             }
4119           }
4120           break;
4121         case LayoutNavEntry::NamespaceMembers: 
4122           msg("Generating namespace member index...\n");
4123           writeNamespaceMemberIndex(ol);
4124           break;
4125         case LayoutNavEntry::Classes: 
4126           if (annotatedClasses>0 && addToIndex)
4127           {
4128             Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0); 
4129             Doxygen::indexList->incContentsDepth();
4130             needsClosing=TRUE;
4131           }
4132           if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Classes)!=lne) // for backward compatibility with old layout file
4133           {
4134             msg("Generating annotated compound index...\n");
4135             writeAnnotatedIndex(ol);
4136           }
4137           break;
4138         case LayoutNavEntry::ClassList: 
4139           msg("Generating annotated compound index...\n");
4140           writeAnnotatedIndex(ol);
4141           break;
4142         case LayoutNavEntry::ClassIndex:
4143           msg("Generating alphabetical compound index...\n");
4144           writeAlphabeticalIndex(ol);
4145           break;
4146         case LayoutNavEntry::ClassHierarchy: 
4147           msg("Generating hierarchical class index...\n");
4148           writeHierarchicalIndex(ol);
4149           if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY"))
4150           {
4151             msg("Generating graphical class hierarchy...\n");
4152             writeGraphicalClassHierarchy(ol);
4153           }
4154           break;
4155         case LayoutNavEntry::ClassMembers: 
4156           msg("Generating member index...\n");
4157           writeClassMemberIndex(ol);
4158           break;
4159         case LayoutNavEntry::Files: 
4160           {
4161             static bool showFiles = Config_getBool("SHOW_FILES");
4162             if (showFiles)
4163             {
4164               if (documentedHtmlFiles>0 && addToIndex)
4165               {
4166                 Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0); 
4167                 Doxygen::indexList->incContentsDepth();
4168                 needsClosing=TRUE;
4169               }
4170               if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files)!=lne) // for backward compatibility with old layout file
4171               {
4172                 msg("Generating file index...\n");
4173                 writeFileIndex(ol);
4174               }
4175             }
4176           }
4177           break;
4178         case LayoutNavEntry::FileList: 
4179           {
4180             static bool showFiles = Config_getBool("SHOW_FILES");
4181             if (showFiles)
4182             {
4183               msg("Generating file index...\n");
4184               writeFileIndex(ol);
4185             }
4186           }
4187           break;
4188         case LayoutNavEntry::FileGlobals: 
4189           msg("Generating file member index...\n");
4190           writeFileMemberIndex(ol);
4191           break;
4192         case LayoutNavEntry::Examples: 
4193           msg("Generating example index...\n");
4194           writeExampleIndex(ol);
4195           break;
4196         case LayoutNavEntry::User: 
4197           {
4198             // prepend a ! or ^ marker to the URL to avoid tampering with it
4199             QCString url = correctURL(lne->url(),"!"); // add ! to relative URL
4200             bool isRelative=url.at(0)=='!';
4201             if (!url.isEmpty() && !isRelative) // absolute URL
4202             {
4203               url.prepend("^"); // prepend ^ to absolute URL
4204             }
4205             bool isRef = lne->baseFile().left(4)=="@ref" || lne->baseFile().left(4)=="\\ref";
4206             Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,url,0,FALSE,isRef || isRelative); 
4207           }
4208           break;
4209         case LayoutNavEntry::UserGroup:
4210           if (addToIndex)
4211           {
4212             QCString url = correctURL(lne->url(),"!"); // add ! to relative URL
4213             if (!url.isEmpty())
4214             {
4215               if (url=="![none]")
4216               {
4217                 Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0,FALSE,FALSE); 
4218               }
4219               else
4220               {
4221                 bool isRelative=url.at(0)=='!';
4222                 if (!isRelative) // absolute URL
4223                 {
4224                   url.prepend("^"); // prepend ^ to absolute URL
4225                 }
4226                 bool isRef = lne->baseFile().left(4)=="@ref" || lne->baseFile().left(4)=="\\ref";
4227                 Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,url,0,FALSE,isRef || isRelative); 
4228               }
4229             }
4230             else 
4231             {
4232               Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0,TRUE,TRUE); 
4233             }
4234             Doxygen::indexList->incContentsDepth();
4235             needsClosing=TRUE;
4236           }
4237           writeUserGroupStubPage(ol,lne);
4238           break;
4239       }
4240       if (kind!=LayoutNavEntry::User && kind!=LayoutNavEntry::UserGroup) // User entry may appear multiple times
4241       {
4242         indexWritten.at(index)=TRUE;
4243       }
4244     }
4245     writeIndexHierarchyEntries(ol,lne->children());
4246     if (needsClosing)
4247     {
4248       switch(kind)
4249       {
4250         case LayoutNavEntry::Namespaces: 
4251         case LayoutNavEntry::Classes: 
4252         case LayoutNavEntry::Files: 
4253         case LayoutNavEntry::UserGroup: 
4254           Doxygen::indexList->decContentsDepth();
4255           break;
4256         default:
4257           break;
4258       }
4259     }
4260     //printf("ending %s kind=%d\n",lne->title().data(),lne->kind());
4261   }
4262 }
4263
4264 void writeIndexHierarchy(OutputList &ol)
4265 {
4266   LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry();
4267   if (lne)
4268   {
4269     writeIndexHierarchyEntries(ol,lne->children());
4270   }
4271 }
4272