1 /******************************************************************************
2 *
3 * Copyright (C) 1997-2021 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16 /** @file
17 * @brief This file contains functions for the various index pages.
18 */
19
20 #include <cstdlib>
21 #include <sstream>
22 #include <array>
23
24 #include <assert.h>
25
26 #include "message.h"
27 #include "index.h"
28 #include "doxygen.h"
29 #include "config.h"
30 #include "filedef.h"
31 #include "outputlist.h"
32 #include "util.h"
33 #include "groupdef.h"
34 #include "language.h"
35 #include "htmlgen.h"
36 #include "htmlhelp.h"
37 #include "ftvhelp.h"
38 #include "dot.h"
39 #include "dotgfxhierarchytable.h"
40 #include "dotlegendgraph.h"
41 #include "pagedef.h"
42 #include "dirdef.h"
43 #include "vhdldocgen.h"
44 #include "layout.h"
45 #include "memberlist.h"
46 #include "classlist.h"
47 #include "namespacedef.h"
48 #include "filename.h"
49 #include "tooltip.h"
50 #include "utf8.h"
51
52 #define MAX_ITEMS_BEFORE_MULTIPAGE_INDEX 200
53 #define MAX_ITEMS_BEFORE_QUICK_INDEX 30
54
55
56 int annotatedClasses;
57 int annotatedClassesPrinted;
58 int hierarchyClasses;
59 int annotatedInterfaces;
60 int annotatedInterfacesPrinted;
61 int hierarchyInterfaces;
62 int annotatedStructs;
63 int annotatedStructsPrinted;
64 int annotatedExceptions;
65 int annotatedExceptionsPrinted;
66 int hierarchyExceptions;
67 int documentedGroups;
68 int documentedNamespaces;
69 int documentedConcepts;
70 int indexedPages;
71 int documentedClassMembers[CMHL_Total];
72 int documentedFileMembers[FMHL_Total];
73 int documentedNamespaceMembers[NMHL_Total];
74 int documentedFiles;
75 int documentedPages;
76 int documentedDirs;
77
78 static int countClassHierarchy(ClassDef::CompoundType ct);
79 static void countFiles(int &htmlFiles,int &files);
80 static int countGroups();
81 static int countDirs();
82 static int countNamespaces();
83 static int countConcepts();
84 static int countAnnotatedClasses(int *cp,ClassDef::CompoundType ct);
85 static void countRelatedPages(int &docPages,int &indexPages);
86
countDataStructures()87 void countDataStructures()
88 {
89 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
90 annotatedClasses = countAnnotatedClasses(&annotatedClassesPrinted, ClassDef::Class); // "classes" + "annotated"
91 hierarchyClasses = countClassHierarchy(ClassDef::Class); // "hierarchy"
92 // "interfaces" + "annotated"
93 annotatedInterfaces = sliceOpt ? countAnnotatedClasses(&annotatedInterfacesPrinted, ClassDef::Interface) : 0;
94 // "interfacehierarchy"
95 hierarchyInterfaces = sliceOpt ? countClassHierarchy(ClassDef::Interface) : 0;
96 // "structs" + "annotated"
97 annotatedStructs = sliceOpt ? countAnnotatedClasses(&annotatedStructsPrinted, ClassDef::Struct) : 0;
98 // "exceptions" + "annotated"
99 annotatedExceptions = sliceOpt ? countAnnotatedClasses(&annotatedExceptionsPrinted, ClassDef::Exception) : 0;
100 // "exceptionhierarchy"
101 hierarchyExceptions = sliceOpt ? countClassHierarchy(ClassDef::Exception) : 0;
102 countFiles(documentedFiles,documentedFiles); // "files"
103 countRelatedPages(documentedPages,indexedPages); // "pages"
104 documentedGroups = countGroups(); // "modules"
105 documentedNamespaces = countNamespaces(); // "namespaces"
106 documentedConcepts = countConcepts(); // "concepts"
107 documentedDirs = countDirs(); // "dirs"
108 // "globals"
109 // "namespacemembers"
110 // "functions"
111 }
112
startIndexHierarchy(OutputList & ol,int level)113 static void startIndexHierarchy(OutputList &ol,int level)
114 {
115 ol.pushGeneratorState();
116 ol.disable(OutputGenerator::Man);
117 ol.disable(OutputGenerator::Html);
118 if (level<6) ol.startIndexList();
119 ol.popGeneratorState();
120
121 ol.pushGeneratorState();
122 ol.disable(OutputGenerator::Latex);
123 ol.disable(OutputGenerator::RTF);
124 ol.disable(OutputGenerator::Docbook);
125 ol.startItemList();
126 ol.popGeneratorState();
127 }
128
endIndexHierarchy(OutputList & ol,int level)129 static void endIndexHierarchy(OutputList &ol,int level)
130 {
131 ol.pushGeneratorState();
132 ol.disable(OutputGenerator::Man);
133 ol.disable(OutputGenerator::Html);
134 if (level<6) ol.endIndexList();
135 ol.popGeneratorState();
136
137 ol.pushGeneratorState();
138 ol.disable(OutputGenerator::Latex);
139 ol.disable(OutputGenerator::Docbook);
140 ol.disable(OutputGenerator::RTF);
141 ol.endItemList();
142 ol.popGeneratorState();
143 }
144
145 //----------------------------------------------------------------------------
146
147 using MemberIndexList = std::vector<const MemberDef *>;
148 using MemberIndexMap = std::map<std::string,MemberIndexList>;
149
150 static std::array<MemberIndexMap,CMHL_Total> g_classIndexLetterUsed;
151 static std::array<MemberIndexMap,FMHL_Total> g_fileIndexLetterUsed;
152 static std::array<MemberIndexMap,NMHL_Total> g_namespaceIndexLetterUsed;
153
MemberIndexMap_add(MemberIndexMap & map,const std::string & letter,const MemberDef * md)154 void MemberIndexMap_add(MemberIndexMap &map,const std::string &letter,const MemberDef *md)
155 {
156 auto it = map.find(letter);
157 if (it!=map.end())
158 {
159 it->second.push_back(md);
160 }
161 else
162 {
163 map.insert(std::make_pair(letter,std::vector<const MemberDef*>({md})));
164 }
165 }
166
167 const int maxItemsBeforeQuickIndex = MAX_ITEMS_BEFORE_QUICK_INDEX;
168
169 //----------------------------------------------------------------------------
170
171 //----------------------------------------------------------------------------
172
startQuickIndexList(OutputList & ol,bool letterTabs=FALSE)173 static void startQuickIndexList(OutputList &ol,bool letterTabs=FALSE)
174 {
175 if (letterTabs)
176 {
177 ol.writeString(" <div id=\"navrow4\" class=\"tabs3\">\n");
178 }
179 else
180 {
181 ol.writeString(" <div id=\"navrow3\" class=\"tabs2\">\n");
182 }
183 ol.writeString(" <ul class=\"tablist\">\n");
184 }
185
endQuickIndexList(OutputList & ol)186 static void endQuickIndexList(OutputList &ol)
187 {
188 ol.writeString(" </ul>\n");
189 ol.writeString(" </div>\n");
190 }
191
startQuickIndexItem(OutputList & ol,const QCString & l,bool hl,bool compact,bool & first)192 static void startQuickIndexItem(OutputList &ol,const QCString &l,
193 bool hl,bool compact,bool &first)
194 {
195 first=FALSE;
196 ol.writeString(" <li");
197 if (hl) ol.writeString(" class=\"current\"");
198 ol.writeString("><a ");
199 ol.writeString("href=\"");
200 ol.writeString(l);
201 ol.writeString("\">");
202 ol.writeString("<span>");
203 }
204
endQuickIndexItem(OutputList & ol)205 static void endQuickIndexItem(OutputList &ol)
206 {
207 ol.writeString("</span>");
208 ol.writeString("</a>");
209 ol.writeString("</li>\n");
210 }
211
212 // don't make this static as it is called from a template function and some
213 // old compilers don't support calls to static functions from a template.
fixSpaces(const QCString & s)214 QCString fixSpaces(const QCString &s)
215 {
216 return substitute(s," "," ");
217 }
218
startTitle(OutputList & ol,const QCString & fileName,const DefinitionMutable * def)219 void startTitle(OutputList &ol,const QCString &fileName,const DefinitionMutable *def)
220 {
221 ol.startHeaderSection();
222 if (def) def->writeSummaryLinks(ol);
223 ol.startTitleHead(fileName);
224 ol.pushGeneratorState();
225 ol.disable(OutputGenerator::Man);
226 }
227
endTitle(OutputList & ol,const QCString & fileName,const QCString & name)228 void endTitle(OutputList &ol,const QCString &fileName,const QCString &name)
229 {
230 ol.popGeneratorState();
231 ol.endTitleHead(fileName,name);
232 ol.endHeaderSection();
233 }
234
startFile(OutputList & ol,const QCString & name,const QCString & manName,const QCString & title,HighlightedItem hli,bool additionalIndices,const QCString & altSidebarName)235 void startFile(OutputList &ol,const QCString &name,const QCString &manName,
236 const QCString &title,HighlightedItem hli,bool additionalIndices,
237 const QCString &altSidebarName)
238 {
239 static bool disableIndex = Config_getBool(DISABLE_INDEX);
240 ol.startFile(name,manName,title);
241 ol.startQuickIndices();
242 if (!disableIndex)
243 {
244 ol.writeQuickLinks(TRUE,hli,name);
245 }
246 if (!additionalIndices)
247 {
248 ol.endQuickIndices();
249 }
250 ol.writeSplitBar(!altSidebarName.isEmpty() ? altSidebarName : name);
251 ol.writeSearchInfo();
252 }
253
endFile(OutputList & ol,bool skipNavIndex,bool skipEndContents,const QCString & navPath)254 void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents,
255 const QCString &navPath)
256 {
257 static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
258 ol.pushGeneratorState();
259 ol.disableAllBut(OutputGenerator::Html);
260 if (!skipNavIndex)
261 {
262 if (!skipEndContents) ol.endContents();
263 if (generateTreeView)
264 {
265 ol.writeString("</div><!-- doc-content -->\n");
266 }
267 }
268
269 ol.writeFooter(navPath); // write the footer
270 ol.popGeneratorState();
271 ol.endFile();
272 }
273
endFileWithNavPath(const Definition * d,OutputList & ol)274 void endFileWithNavPath(const Definition *d,OutputList &ol)
275 {
276 static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
277 QCString navPath;
278 if (generateTreeView)
279 {
280 ol.pushGeneratorState();
281 ol.disableAllBut(OutputGenerator::Html);
282 ol.writeString("</div><!-- doc-content -->\n");
283 ol.popGeneratorState();
284 navPath = d->navigationPathAsString();
285 }
286 endFile(ol,generateTreeView,TRUE,navPath);
287 }
288
289 //----------------------------------------------------------------------
290
writeMemberToIndex(const Definition * def,const MemberDef * md,bool addToIndex)291 static void writeMemberToIndex(const Definition *def,const MemberDef *md,bool addToIndex)
292 {
293 bool isAnonymous = md->isAnonymous();
294 bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
295 const MemberVector &enumList = md->enumFieldList();
296 bool isDir = !enumList.empty() && md->isEnumerate();
297 if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope)
298 {
299 Doxygen::indexList->addContentsItem(isDir,
300 md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex && md->getGroupDef()==nullptr);
301 }
302 else // inherited member
303 {
304 Doxygen::indexList->addContentsItem(isDir,
305 md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex && md->getGroupDef()==nullptr);
306 }
307 if (isDir)
308 {
309 if (!isAnonymous)
310 {
311 Doxygen::indexList->incContentsDepth();
312 }
313 for (const auto &emd : enumList)
314 {
315 if (!hideUndocMembers || emd->hasDocumentation())
316 {
317 if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope)
318 {
319 Doxygen::indexList->addContentsItem(FALSE,
320 emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex && emd->getGroupDef()==nullptr);
321 }
322 else // inherited member
323 {
324 Doxygen::indexList->addContentsItem(FALSE,
325 emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex && emd->getGroupDef()==nullptr);
326 }
327 }
328 }
329 if (!isAnonymous)
330 {
331 Doxygen::indexList->decContentsDepth();
332 }
333 }
334 }
335
336 //----------------------------------------------------------------------
337 template<class T>
addMembersToIndex(T * def,LayoutDocManager::LayoutPart part,const QCString & name,const QCString & anchor,bool addToIndex=TRUE,bool preventSeparateIndex=FALSE,const ConceptLinkedRefMap * concepts=nullptr)338 void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
339 const QCString &name,const QCString &anchor,
340 bool addToIndex=TRUE,bool preventSeparateIndex=FALSE,
341 const ConceptLinkedRefMap *concepts = nullptr)
342
343 {
344 bool hasMembers = !def->getMemberLists().empty() || !def->getMemberGroups().empty();
345 Doxygen::indexList->addContentsItem(hasMembers,name,
346 def->getReference(),def->getOutputFileBase(),anchor,
347 hasMembers && !preventSeparateIndex,
348 addToIndex,
349 def);
350 int numClasses=0;
351 for (const auto &cd : def->getClasses())
352 {
353 if (cd->isLinkable()) numClasses++;
354 }
355 int numConcepts=0;
356 if (concepts)
357 {
358 for (const auto &cd : *concepts)
359 {
360 if (cd->isLinkable()) numConcepts++;
361 }
362 }
363 //printf("addMembersToIndex(def=%s hasMembers=%d numClasses=%d)\n",qPrint(def->name()),hasMembers,numClasses);
364 if (hasMembers || numClasses>0 || numConcepts>0)
365 {
366 Doxygen::indexList->incContentsDepth();
367 for (const auto &lde : LayoutDocManager::instance().docEntries(part))
368 {
369 auto kind = lde->kind();
370 if (kind==LayoutDocEntry::MemberDef)
371 {
372 const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
373 MemberList *ml = def->getMemberList(lmd->type);
374 if (ml)
375 {
376 for (const auto &md : *ml)
377 {
378 if (md->visibleInIndex())
379 {
380 writeMemberToIndex(def,md,addToIndex);
381 }
382 }
383 }
384 }
385 else if (kind==LayoutDocEntry::NamespaceClasses ||
386 kind==LayoutDocEntry::FileClasses ||
387 kind==LayoutDocEntry::ClassNestedClasses
388 )
389 {
390 for (const auto &cd : def->getClasses())
391 {
392 if (cd->isLinkable() && (cd->partOfGroups().empty() || def->definitionType()==Definition::TypeGroup))
393 {
394 static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS);
395 bool isNestedClass = def->definitionType()==Definition::TypeClass;
396 addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(lde->kind()==LayoutDocEntry::FileClasses),cd->anchor(),
397 addToIndex && (isNestedClass || (cd->isSimple() && inlineSimpleStructs)),
398 preventSeparateIndex || cd->isEmbeddedInOuterScope());
399 }
400 }
401 }
402 else if (kind==LayoutDocEntry::FileConcepts && concepts)
403 {
404 for (const auto &cd : *concepts)
405 {
406 if (cd->isLinkable() && (cd->partOfGroups().empty() || def->definitionType()==Definition::TypeGroup))
407 {
408 Doxygen::indexList->addContentsItem(false,cd->displayName(),
409 cd->getReference(),cd->getOutputFileBase(),QCString(),
410 addToIndex,
411 false,
412 cd);
413 }
414 }
415 }
416 }
417
418 Doxygen::indexList->decContentsDepth();
419 }
420 }
421
422
423 //----------------------------------------------------------------------------
424 /*! Generates HTML Help tree of classes */
425
writeClassTreeToOutput(OutputList & ol,const BaseClassList & bcl,int level,FTVHelp * ftv,bool addToIndex,ClassDefSet & visitedClasses)426 static void writeClassTreeToOutput(OutputList &ol,const BaseClassList &bcl,int level,FTVHelp* ftv,bool addToIndex,ClassDefSet &visitedClasses)
427 {
428 if (bcl.empty()) return;
429 bool started=FALSE;
430 for (const auto &bcd : bcl)
431 {
432 ClassDef *cd=bcd.classDef;
433 if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
434 {
435 continue;
436 }
437
438 bool b;
439 if (cd->getLanguage()==SrcLangExt_VHDL)
440 {
441 b=hasVisibleRoot(cd->subClasses());
442 }
443 else
444 {
445 b=hasVisibleRoot(cd->baseClasses());
446 }
447
448 if (cd->isVisibleInHierarchy() && b) // hasVisibleRoot(cd->baseClasses()))
449 {
450 if (!started)
451 {
452 startIndexHierarchy(ol,level);
453 if (addToIndex)
454 {
455 Doxygen::indexList->incContentsDepth();
456 }
457 if (ftv)
458 {
459 ftv->incContentsDepth();
460 }
461 started=TRUE;
462 }
463 ol.startIndexListItem();
464 //printf("Passed...\n");
465 bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() &&
466 classHasVisibleChildren(cd);
467 //printf("tree4: Has children %s: %d\n",qPrint(cd->name()),hasChildren);
468 if (cd->isLinkable())
469 {
470 //printf("Writing class %s\n",qPrint(cd->displayName()));
471 ol.startIndexItem(cd->getReference(),cd->getOutputFileBase());
472 ol.parseText(cd->displayName());
473 ol.endIndexItem(cd->getReference(),cd->getOutputFileBase());
474 if (cd->isReference())
475 {
476 ol.startTypewriter();
477 ol.docify(" [external]");
478 ol.endTypewriter();
479 }
480 if (addToIndex)
481 {
482 Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor());
483 }
484 if (ftv)
485 {
486 if (cd->getLanguage()==SrcLangExt_VHDL)
487 {
488 ftv->addContentsItem(hasChildren,bcd.usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd);
489 }
490 else
491 {
492 ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd);
493 }
494 }
495 }
496 else
497 {
498 ol.startIndexItem(QCString(),QCString());
499 ol.parseText(cd->name());
500 ol.endIndexItem(QCString(),QCString());
501 if (addToIndex)
502 {
503 Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),QCString(),QCString(),QCString());
504 }
505 if (ftv)
506 {
507 ftv->addContentsItem(hasChildren,cd->displayName(),QCString(),QCString(),QCString(),FALSE,FALSE,cd);
508 }
509 }
510 if (hasChildren)
511 {
512 //printf("Class %s at %p visited=%d\n",qPrint(cd->name()),cd,cd->visited);
513 visitedClasses.insert(cd);
514 if (cd->getLanguage()==SrcLangExt_VHDL)
515 {
516 writeClassTreeToOutput(ol,cd->baseClasses(),level+1,ftv,addToIndex,visitedClasses);
517 }
518 else
519 {
520 writeClassTreeToOutput(ol,cd->subClasses(),level+1,ftv,addToIndex,visitedClasses);
521 }
522 }
523 ol.endIndexListItem();
524 }
525 }
526 if (started)
527 {
528 endIndexHierarchy(ol,level);
529 if (addToIndex)
530 {
531 Doxygen::indexList->decContentsDepth();
532 }
533 if (ftv)
534 {
535 ftv->decContentsDepth();
536 }
537 }
538 }
539
540 //----------------------------------------------------------------------------
541
dirHasVisibleChildren(const DirDef * dd)542 static bool dirHasVisibleChildren(const DirDef *dd)
543 {
544 if (dd->hasDocumentation()) return TRUE;
545
546 for (const auto &fd : dd->getFiles())
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 for(const auto &subdd : dd->subDirs())
560 {
561 if (dirHasVisibleChildren(subdd))
562 {
563 return TRUE;
564 }
565 }
566 return FALSE;
567 }
568
569 //----------------------------------------------------------------------------
writeDirTreeNode(OutputList & ol,const DirDef * dd,int level,FTVHelp * ftv,bool addToIndex)570 static void writeDirTreeNode(OutputList &ol, const DirDef *dd, int level, FTVHelp* ftv,bool addToIndex)
571 {
572 if (level>20)
573 {
574 warn(dd->getDefFileName(),dd->getDefLine(),
575 "maximum nesting level exceeded for directory %s: "
576 "check for possible recursive directory relation!\n",qPrint(dd->name())
577 );
578 return;
579 }
580
581 if (!dirHasVisibleChildren(dd))
582 {
583 return;
584 }
585
586 static bool tocExpand = TRUE; //Config_getBool(TOC_EXPAND);
587 bool isDir = !dd->subDirs().empty() || // there are subdirs
588 (tocExpand && // or toc expand and
589 !dd->getFiles().empty() // there are files
590 );
591 //printf("gd='%s': pageDict=%d\n",qPrint(gd->name()),gd->pageDict->count());
592 if (addToIndex)
593 {
594 Doxygen::indexList->addContentsItem(isDir,dd->shortName(),dd->getReference(),dd->getOutputFileBase(),QCString(),TRUE,TRUE);
595 Doxygen::indexList->incContentsDepth();
596 }
597 if (ftv)
598 {
599 ftv->addContentsItem(isDir,dd->shortName(),dd->getReference(),
600 dd->getOutputFileBase(),QCString(),FALSE,TRUE,dd);
601 ftv->incContentsDepth();
602 }
603
604 ol.startIndexListItem();
605 ol.startIndexItem(dd->getReference(),dd->getOutputFileBase());
606 ol.parseText(dd->shortName());
607 ol.endIndexItem(dd->getReference(),dd->getOutputFileBase());
608 if (dd->isReference())
609 {
610 ol.startTypewriter();
611 ol.docify(" [external]");
612 ol.endTypewriter();
613 }
614
615 // write sub directories
616 if (dd->subDirs().size()>0)
617 {
618 startIndexHierarchy(ol,level+1);
619 for(const auto &subdd : dd->subDirs())
620 {
621 writeDirTreeNode(ol,subdd,level+1,ftv,addToIndex);
622 }
623 endIndexHierarchy(ol,level+1);
624 }
625
626 int fileCount=0;
627 if (!dd->getFiles().empty())
628 {
629 for (const auto &fd : dd->getFiles())
630 {
631 //static bool allExternals = Config_getBool(ALLEXTERNALS);
632 //if ((allExternals && fd->isLinkable()) || fd->isLinkableInProject())
633 //{
634 // fileCount++;
635 //}
636 bool genSourceFile;
637 if (fileVisibleInIndex(fd,genSourceFile))
638 {
639 fileCount++;
640 }
641 else if (genSourceFile)
642 {
643 fileCount++;
644 }
645 }
646 if (fileCount>0)
647 {
648 startIndexHierarchy(ol,level+1);
649 for (const auto &fd : dd->getFiles())
650 {
651 bool doc,src;
652 doc = fileVisibleInIndex(fd,src);
653 QCString reference;
654 QCString outputBase;
655 if (doc)
656 {
657 reference = fd->getReference();
658 outputBase = fd->getOutputFileBase();
659 }
660 if (doc || src)
661 {
662 ol.startIndexListItem();
663 ol.startIndexItem(reference,outputBase);
664 ol.parseText(fd->displayName());
665 ol.endIndexItem(reference,outputBase);
666 ol.endIndexListItem();
667 if (ftv && (src || doc))
668 {
669 ftv->addContentsItem(FALSE,
670 fd->displayName(),
671 reference,outputBase,
672 QCString(),FALSE,FALSE,fd);
673 }
674 }
675 }
676 endIndexHierarchy(ol,level+1);
677 }
678 }
679
680 if (tocExpand && addToIndex)
681 {
682 // write files of this directory
683 if (fileCount>0)
684 {
685 for (const auto &fd : dd->getFiles())
686 {
687 //static bool allExternals = Config_getBool(ALLEXTERNALS);
688 //if ((allExternals && fd->isLinkable()) || fd->isLinkableInProject())
689 bool doc,src;
690 doc = fileVisibleInIndex(fd,src);
691 if (doc)
692 {
693 addMembersToIndex(fd,LayoutDocManager::File,fd->displayName(),QCString(),
694 TRUE,FALSE,&fd->getConcepts());
695 }
696 else if (src)
697 {
698 Doxygen::indexList->addContentsItem(
699 FALSE, fd->name(), QCString(),
700 fd->getSourceFileBase(), QCString(), FALSE, TRUE, fd);
701 }
702 }
703 }
704 }
705 ol.endIndexListItem();
706
707 if (addToIndex)
708 {
709 Doxygen::indexList->decContentsDepth();
710 }
711 if (ftv)
712 {
713 ftv->decContentsDepth();
714 }
715 }
716
writeDirHierarchy(OutputList & ol,FTVHelp * ftv,bool addToIndex)717 static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
718 {
719 if (ftv)
720 {
721 ol.pushGeneratorState();
722 ol.disable(OutputGenerator::Html);
723 }
724 startIndexHierarchy(ol,0);
725 for (const auto &dd : *Doxygen::dirLinkedMap)
726 {
727 if (dd->getOuterScope()==Doxygen::globalScope)
728 {
729 writeDirTreeNode(ol,dd.get(),0,ftv,addToIndex);
730 }
731 }
732 if (ftv)
733 {
734 for (const auto &fn : *Doxygen::inputNameLinkedMap)
735 {
736 for (const auto &fd : *fn)
737 {
738 if (fd->getDirDef()==0) // top level file
739 {
740 bool src;
741 bool doc = fileVisibleInIndex(fd.get(),src);
742 QCString reference, outputBase;
743 if (doc)
744 {
745 reference = fd->getReference();
746 outputBase = fd->getOutputFileBase();
747 }
748 if (doc || src)
749 {
750 ftv->addContentsItem(FALSE,fd->displayName(),
751 reference, outputBase, QCString(),
752 FALSE,FALSE,fd.get());
753 }
754 if (addToIndex)
755 {
756 if (doc)
757 {
758 addMembersToIndex(fd.get(),LayoutDocManager::File,fd->displayName(),QCString(),TRUE,FALSE,&fd->getConcepts());
759 }
760 else if (src)
761 {
762 Doxygen::indexList->addContentsItem(
763 FALSE, fd->name(), QCString(),
764 fd->getSourceFileBase(), QCString(), FALSE, TRUE, fd.get());
765 }
766 }
767 }
768 }
769 }
770 }
771 endIndexHierarchy(ol,0);
772 if (ftv)
773 {
774 ol.popGeneratorState();
775 }
776 }
777
778
779 //----------------------------------------------------------------------------
780
writeClassTreeForList(OutputList & ol,const ClassLinkedMap & cl,bool & started,FTVHelp * ftv,bool addToIndex,ClassDef::CompoundType ct,ClassDefSet & visitedClasses)781 static void writeClassTreeForList(OutputList &ol,const ClassLinkedMap &cl,bool &started,FTVHelp* ftv,bool addToIndex,
782 ClassDef::CompoundType ct,ClassDefSet &visitedClasses)
783 {
784 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
785 for (const auto &cd : cl)
786 {
787 //printf("class %s hasVisibleRoot=%d isVisibleInHierarchy=%d\n",
788 // qPrint(cd->name()),
789 // hasVisibleRoot(cd->baseClasses()),
790 // cd->isVisibleInHierarchy()
791 // );
792 bool b;
793 if (cd->getLanguage()==SrcLangExt_VHDL)
794 {
795 if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
796 {
797 continue;
798 }
799 b=!hasVisibleRoot(cd->subClasses());
800 }
801 else if (sliceOpt && cd->compoundType() != ct)
802 {
803 continue;
804 }
805 else
806 {
807 b=!hasVisibleRoot(cd->baseClasses());
808 }
809
810 if (b) //filter on root classes
811 {
812 if (cd->isVisibleInHierarchy()) // should it be visible
813 {
814 if (!started)
815 {
816 startIndexHierarchy(ol,0);
817 if (addToIndex)
818 {
819 Doxygen::indexList->incContentsDepth();
820 }
821 started=TRUE;
822 }
823 ol.startIndexListItem();
824 bool hasChildren = visitedClasses.find(cd.get())==visitedClasses.end() &&
825 classHasVisibleChildren(cd.get());
826 //printf("list: Has children %s: %d\n",qPrint(cd->name()),hasChildren);
827 if (cd->isLinkable())
828 {
829 //printf("Writing class %s isLinkable()=%d isLinkableInProject()=%d cd->templateMaster()=%p\n",
830 // qPrint(cd->displayName()),cd->isLinkable(),cd->isLinkableInProject(),cd->templateMaster());
831 ol.startIndexItem(cd->getReference(),cd->getOutputFileBase());
832 ol.parseText(cd->displayName());
833 ol.endIndexItem(cd->getReference(),cd->getOutputFileBase());
834 if (cd->isReference())
835 {
836 ol.startTypewriter();
837 ol.docify(" [external]");
838 ol.endTypewriter();
839 }
840 if (addToIndex)
841 {
842 if (cd->getLanguage()!=SrcLangExt_VHDL) // prevents double insertion in Design Unit List
843 Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE);
844 }
845 if (ftv)
846 {
847 ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd.get());
848 }
849 }
850 else
851 {
852 ol.startIndexItem(QCString(),QCString());
853 ol.parseText(cd->displayName());
854 ol.endIndexItem(QCString(),QCString());
855 if (addToIndex)
856 {
857 Doxygen::indexList->addContentsItem(hasChildren,cd->displayName(),QCString(),QCString(),QCString(),FALSE,FALSE);
858 }
859 if (ftv)
860 {
861 ftv->addContentsItem(hasChildren,cd->displayName(),QCString(),QCString(),QCString(),FALSE,FALSE,cd.get());
862 }
863 }
864 if (cd->getLanguage()==SrcLangExt_VHDL && hasChildren)
865 {
866 writeClassTreeToOutput(ol,cd->baseClasses(),1,ftv,addToIndex,visitedClasses);
867 visitedClasses.insert(cd.get());
868 }
869 else if (hasChildren)
870 {
871 writeClassTreeToOutput(ol,cd->subClasses(),1,ftv,addToIndex,visitedClasses);
872 visitedClasses.insert(cd.get());
873 }
874 ol.endIndexListItem();
875 }
876 }
877 }
878 }
879
writeClassHierarchy(OutputList & ol,FTVHelp * ftv,bool addToIndex,ClassDef::CompoundType ct)880 static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex,ClassDef::CompoundType ct)
881 {
882 ClassDefSet visitedClasses;
883 if (ftv)
884 {
885 ol.pushGeneratorState();
886 ol.disable(OutputGenerator::Html);
887 }
888 bool started=FALSE;
889 writeClassTreeForList(ol,*Doxygen::classLinkedMap,started,ftv,addToIndex,ct,visitedClasses);
890 writeClassTreeForList(ol,*Doxygen::hiddenClassLinkedMap,started,ftv,addToIndex,ct,visitedClasses);
891 if (started)
892 {
893 endIndexHierarchy(ol,0);
894 if (addToIndex)
895 {
896 Doxygen::indexList->decContentsDepth();
897 }
898 }
899 if (ftv)
900 {
901 ol.popGeneratorState();
902 }
903 }
904
905 //----------------------------------------------------------------------------
906
countClassesInTreeList(const ClassLinkedMap & cl,ClassDef::CompoundType ct)907 static int countClassesInTreeList(const ClassLinkedMap &cl, ClassDef::CompoundType ct)
908 {
909 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
910 int count=0;
911 for (const auto &cd : cl)
912 {
913 if (sliceOpt && cd->compoundType() != ct)
914 {
915 continue;
916 }
917 if (!hasVisibleRoot(cd->baseClasses())) // filter on root classes
918 {
919 if (cd->isVisibleInHierarchy()) // should it be visible
920 {
921 if (!cd->subClasses().empty()) // should have sub classes
922 {
923 count++;
924 }
925 }
926 }
927 }
928 return count;
929 }
930
countClassHierarchy(ClassDef::CompoundType ct)931 static int countClassHierarchy(ClassDef::CompoundType ct)
932 {
933 int count=0;
934 count+=countClassesInTreeList(*Doxygen::classLinkedMap, ct);
935 count+=countClassesInTreeList(*Doxygen::hiddenClassLinkedMap, ct);
936 return count;
937 }
938
939 //----------------------------------------------------------------------------
940
writeHierarchicalIndex(OutputList & ol)941 static void writeHierarchicalIndex(OutputList &ol)
942 {
943 if (hierarchyClasses==0) return;
944 ol.pushGeneratorState();
945 //1.{
946 ol.disable(OutputGenerator::Man);
947 ol.disable(OutputGenerator::Docbook);
948
949 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy);
950 QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
951 bool addToIndex = lne==0 || lne->visible();
952
953 startFile(ol,"hierarchy",QCString(), title, HLI_ClassHierarchy);
954 startTitle(ol,QCString());
955 ol.parseText(title);
956 endTitle(ol,QCString(),QCString());
957 ol.startContents();
958 ol.startTextBlock();
959
960 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
961 {
962 ol.pushGeneratorState();
963 ol.disable(OutputGenerator::Latex);
964 ol.disable(OutputGenerator::RTF);
965 ol.disable(OutputGenerator::Docbook);
966 ol.startParagraph();
967 ol.startTextLink("inherits",QCString());
968 ol.parseText(theTranslator->trGotoGraphicalHierarchy());
969 ol.endTextLink();
970 ol.endParagraph();
971 ol.popGeneratorState();
972 }
973 ol.parseText(lne ? lne->intro() : theTranslator->trClassHierarchyDescription());
974 ol.endTextBlock();
975
976 // ---------------
977 // Static class hierarchy for Latex/RTF
978 // ---------------
979 ol.pushGeneratorState();
980 //2.{
981 ol.disable(OutputGenerator::Html);
982 Doxygen::indexList->disable();
983
984 writeClassHierarchy(ol,0,addToIndex,ClassDef::Class);
985
986 Doxygen::indexList->enable();
987 ol.popGeneratorState();
988 //2.}
989
990 // ---------------
991 // Dynamic class hierarchical index for HTML
992 // ---------------
993 ol.pushGeneratorState();
994 //2.{
995 ol.disableAllBut(OutputGenerator::Html);
996
997 {
998 if (addToIndex)
999 {
1000 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"hierarchy",QCString(),TRUE,TRUE);
1001 }
1002 FTVHelp* ftv = new FTVHelp(FALSE);
1003 writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Class);
1004 TextStream t;
1005 ftv->generateTreeViewInline(t);
1006 ol.pushGeneratorState();
1007 ol.disableAllBut(OutputGenerator::Html);
1008 ol.writeString(t.str().c_str());
1009 ol.popGeneratorState();
1010 delete ftv;
1011 }
1012 ol.popGeneratorState();
1013 //2.}
1014 // ------
1015
1016 endFile(ol);
1017 ol.popGeneratorState();
1018 //1.}
1019 }
1020
1021 //----------------------------------------------------------------------------
1022
writeGraphicalClassHierarchy(OutputList & ol)1023 static void writeGraphicalClassHierarchy(OutputList &ol)
1024 {
1025 if (hierarchyClasses==0) return;
1026 ol.disableAllBut(OutputGenerator::Html);
1027 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy);
1028 QCString title = lne ? lne->title() : theTranslator->trClassHierarchy();
1029 startFile(ol,"inherits",QCString(),title,HLI_ClassHierarchy,FALSE,"hierarchy");
1030 startTitle(ol,QCString());
1031 ol.parseText(title);
1032 endTitle(ol,QCString(),QCString());
1033 ol.startContents();
1034 ol.startTextBlock();
1035 ol.startParagraph();
1036 ol.startTextLink("hierarchy",QCString());
1037 ol.parseText(theTranslator->trGotoTextualHierarchy());
1038 ol.endTextLink();
1039 ol.endParagraph();
1040 ol.endTextBlock();
1041 DotGfxHierarchyTable g;
1042 ol.writeGraphicalHierarchy(g);
1043 endFile(ol);
1044 ol.enableAll();
1045 }
1046
1047 //----------------------------------------------------------------------------
1048
writeHierarchicalInterfaceIndex(OutputList & ol)1049 static void writeHierarchicalInterfaceIndex(OutputList &ol)
1050 {
1051 if (hierarchyInterfaces==0) return;
1052 ol.pushGeneratorState();
1053 //1.{
1054 ol.disable(OutputGenerator::Man);
1055
1056 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceHierarchy);
1057 QCString title = lne ? lne->title() : theTranslator->trInterfaceHierarchy();
1058 bool addToIndex = lne==0 || lne->visible();
1059
1060 startFile(ol,"interfacehierarchy",QCString(), title, HLI_InterfaceHierarchy);
1061 startTitle(ol,QCString());
1062 ol.parseText(title);
1063 endTitle(ol,QCString(),QCString());
1064 ol.startContents();
1065 ol.startTextBlock();
1066
1067 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
1068 {
1069 ol.disable(OutputGenerator::Latex);
1070 ol.disable(OutputGenerator::RTF);
1071 ol.startParagraph();
1072 ol.startTextLink("interfaceinherits",QCString());
1073 ol.parseText(theTranslator->trGotoGraphicalHierarchy());
1074 ol.endTextLink();
1075 ol.endParagraph();
1076 ol.enable(OutputGenerator::Latex);
1077 ol.enable(OutputGenerator::RTF);
1078 }
1079 ol.parseText(lne ? lne->intro() : theTranslator->trInterfaceHierarchyDescription());
1080 ol.endTextBlock();
1081
1082 // ---------------
1083 // Static interface hierarchy for Latex/RTF
1084 // ---------------
1085 ol.pushGeneratorState();
1086 //2.{
1087 ol.disable(OutputGenerator::Html);
1088 Doxygen::indexList->disable();
1089
1090 writeClassHierarchy(ol,0,addToIndex,ClassDef::Interface);
1091
1092 Doxygen::indexList->enable();
1093 ol.popGeneratorState();
1094 //2.}
1095
1096 // ---------------
1097 // Dynamic interface hierarchical index for HTML
1098 // ---------------
1099 ol.pushGeneratorState();
1100 //2.{
1101 ol.disableAllBut(OutputGenerator::Html);
1102
1103 {
1104 if (addToIndex)
1105 {
1106 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"interfacehierarchy",QCString(),TRUE,TRUE);
1107 }
1108 FTVHelp* ftv = new FTVHelp(FALSE);
1109 writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Interface);
1110 TextStream t;
1111 ftv->generateTreeViewInline(t);
1112 ol.pushGeneratorState();
1113 ol.disableAllBut(OutputGenerator::Html);
1114 ol.writeString(t.str().c_str());
1115 ol.popGeneratorState();
1116 delete ftv;
1117 }
1118 ol.popGeneratorState();
1119 //2.}
1120 // ------
1121
1122 endFile(ol);
1123 ol.popGeneratorState();
1124 //1.}
1125 }
1126
1127 //----------------------------------------------------------------------------
1128
writeGraphicalInterfaceHierarchy(OutputList & ol)1129 static void writeGraphicalInterfaceHierarchy(OutputList &ol)
1130 {
1131 if (hierarchyInterfaces==0) return;
1132 ol.disableAllBut(OutputGenerator::Html);
1133 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceHierarchy);
1134 QCString title = lne ? lne->title() : theTranslator->trInterfaceHierarchy();
1135 startFile(ol,"interfaceinherits",QCString(),title,HLI_InterfaceHierarchy,FALSE,"interfacehierarchy");
1136 startTitle(ol,QCString());
1137 ol.parseText(title);
1138 endTitle(ol,QCString(),QCString());
1139 ol.startContents();
1140 ol.startTextBlock();
1141 ol.startParagraph();
1142 ol.startTextLink("interfacehierarchy",QCString());
1143 ol.parseText(theTranslator->trGotoTextualHierarchy());
1144 ol.endTextLink();
1145 ol.endParagraph();
1146 ol.endTextBlock();
1147 DotGfxHierarchyTable g("interface_",ClassDef::Interface);
1148 ol.writeGraphicalHierarchy(g);
1149 endFile(ol);
1150 ol.enableAll();
1151 }
1152
1153 //----------------------------------------------------------------------------
1154
writeHierarchicalExceptionIndex(OutputList & ol)1155 static void writeHierarchicalExceptionIndex(OutputList &ol)
1156 {
1157 if (hierarchyExceptions==0) return;
1158 ol.pushGeneratorState();
1159 //1.{
1160 ol.disable(OutputGenerator::Man);
1161
1162 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionHierarchy);
1163 QCString title = lne ? lne->title() : theTranslator->trExceptionHierarchy();
1164 bool addToIndex = lne==0 || lne->visible();
1165
1166 startFile(ol,"exceptionhierarchy",QCString(), title, HLI_ExceptionHierarchy);
1167 startTitle(ol,QCString());
1168 ol.parseText(title);
1169 endTitle(ol,QCString(),QCString());
1170 ol.startContents();
1171 ol.startTextBlock();
1172
1173 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
1174 {
1175 ol.disable(OutputGenerator::Latex);
1176 ol.disable(OutputGenerator::RTF);
1177 ol.startParagraph();
1178 ol.startTextLink("exceptioninherits",QCString());
1179 ol.parseText(theTranslator->trGotoGraphicalHierarchy());
1180 ol.endTextLink();
1181 ol.endParagraph();
1182 ol.enable(OutputGenerator::Latex);
1183 ol.enable(OutputGenerator::RTF);
1184 }
1185 ol.parseText(lne ? lne->intro() : theTranslator->trExceptionHierarchyDescription());
1186 ol.endTextBlock();
1187
1188 // ---------------
1189 // Static exception hierarchy for Latex/RTF
1190 // ---------------
1191 ol.pushGeneratorState();
1192 //2.{
1193 ol.disable(OutputGenerator::Html);
1194 Doxygen::indexList->disable();
1195
1196 writeClassHierarchy(ol,0,addToIndex,ClassDef::Exception);
1197
1198 Doxygen::indexList->enable();
1199 ol.popGeneratorState();
1200 //2.}
1201
1202 // ---------------
1203 // Dynamic exception hierarchical index for HTML
1204 // ---------------
1205 ol.pushGeneratorState();
1206 //2.{
1207 ol.disableAllBut(OutputGenerator::Html);
1208
1209 {
1210 if (addToIndex)
1211 {
1212 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"exceptionhierarchy",QCString(),TRUE,TRUE);
1213 }
1214 FTVHelp* ftv = new FTVHelp(FALSE);
1215 writeClassHierarchy(ol,ftv,addToIndex,ClassDef::Exception);
1216 TextStream t;
1217 ftv->generateTreeViewInline(t);
1218 ol.pushGeneratorState();
1219 ol.disableAllBut(OutputGenerator::Html);
1220 ol.writeString(t.str().c_str());
1221 ol.popGeneratorState();
1222 delete ftv;
1223 }
1224 ol.popGeneratorState();
1225 //2.}
1226 // ------
1227
1228 endFile(ol);
1229 ol.popGeneratorState();
1230 //1.}
1231 }
1232
1233 //----------------------------------------------------------------------------
1234
writeGraphicalExceptionHierarchy(OutputList & ol)1235 static void writeGraphicalExceptionHierarchy(OutputList &ol)
1236 {
1237 if (hierarchyExceptions==0) return;
1238 ol.disableAllBut(OutputGenerator::Html);
1239 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionHierarchy);
1240 QCString title = lne ? lne->title() : theTranslator->trExceptionHierarchy();
1241 startFile(ol,"exceptioninherits",QCString(),title,HLI_ExceptionHierarchy,FALSE,"exceptionhierarchy");
1242 startTitle(ol,QCString());
1243 ol.parseText(title);
1244 endTitle(ol,QCString(),QCString());
1245 ol.startContents();
1246 ol.startTextBlock();
1247 ol.startParagraph();
1248 ol.startTextLink("exceptionhierarchy",QCString());
1249 ol.parseText(theTranslator->trGotoTextualHierarchy());
1250 ol.endTextLink();
1251 ol.endParagraph();
1252 ol.endTextBlock();
1253 DotGfxHierarchyTable g("exception_",ClassDef::Exception);
1254 ol.writeGraphicalHierarchy(g);
1255 endFile(ol);
1256 ol.enableAll();
1257 }
1258
1259 //----------------------------------------------------------------------------
1260
countFiles(int & allFiles,int & docFiles)1261 static void countFiles(int &allFiles,int &docFiles)
1262 {
1263 allFiles=0;
1264 docFiles=0;
1265 if (Config_getBool(SHOW_FILES))
1266 {
1267 for (const auto &fn : *Doxygen::inputNameLinkedMap)
1268 {
1269 for (const auto &fd: *fn)
1270 {
1271 bool doc,src;
1272 doc = fileVisibleInIndex(fd.get(),src);
1273 if (doc || src)
1274 {
1275 allFiles++;
1276 }
1277 if (doc)
1278 {
1279 docFiles++;
1280 }
1281 }
1282 }
1283 }
1284 }
1285
writeSingleFileIndex(OutputList & ol,const FileDef * fd)1286 static void writeSingleFileIndex(OutputList &ol,const FileDef *fd)
1287 {
1288 //printf("Found filedef %s\n",qPrint(fd->name()));
1289 bool doc = fd->isLinkableInProject();
1290 bool src = fd->generateSourceFile();
1291 bool nameOk = !fd->isDocumentationFile();
1292 if (nameOk && (doc || src) && !fd->isReference())
1293 {
1294 QCString path;
1295 if (Config_getBool(FULL_PATH_NAMES))
1296 {
1297 path=stripFromPath(fd->getPath());
1298 }
1299 QCString fullName=fd->name();
1300 if (!path.isEmpty())
1301 {
1302 if (path.at(path.length()-1)!='/') fullName.prepend("/");
1303 fullName.prepend(path);
1304 }
1305
1306 ol.startIndexKey();
1307 ol.docify(path);
1308 if (doc)
1309 {
1310 ol.writeObjectLink(QCString(),fd->getOutputFileBase(),QCString(),fd->name());
1311 //if (addToIndex)
1312 //{
1313 // addMembersToIndex(fd,LayoutDocManager::File,fullName,QCString());
1314 //}
1315 }
1316 else if (src)
1317 {
1318 ol.writeObjectLink(QCString(),fd->getSourceFileBase(),QCString(),fd->name());
1319 }
1320 if (doc && src)
1321 {
1322 ol.pushGeneratorState();
1323 ol.disableAllBut(OutputGenerator::Html);
1324 ol.docify(" ");
1325 ol.startTextLink(fd->includeName(),QCString());
1326 ol.docify("[");
1327 ol.parseText(theTranslator->trCode());
1328 ol.docify("]");
1329 ol.endTextLink();
1330 ol.popGeneratorState();
1331 }
1332 ol.endIndexKey();
1333 bool hasBrief = !fd->briefDescription().isEmpty();
1334 ol.startIndexValue(hasBrief);
1335 if (hasBrief)
1336 {
1337 //ol.docify(" (");
1338 ol.generateDoc(
1339 fd->briefFile(),fd->briefLine(),
1340 fd,0,
1341 fd->briefDescription(TRUE),
1342 FALSE, // index words
1343 FALSE, // isExample
1344 QCString(), // example name
1345 TRUE, // single line
1346 TRUE, // link from index
1347 Config_getBool(MARKDOWN_SUPPORT)
1348 );
1349 //ol.docify(")");
1350 }
1351 if (doc)
1352 {
1353 ol.endIndexValue(fd->getOutputFileBase(),hasBrief);
1354 }
1355 else // src
1356 {
1357 ol.endIndexValue(fd->getSourceFileBase(),hasBrief);
1358 }
1359 //ol.popGeneratorState();
1360 // --------------------------------------------------------
1361 }
1362 }
1363
1364 //----------------------------------------------------------------------------
1365
writeFileIndex(OutputList & ol)1366 static void writeFileIndex(OutputList &ol)
1367 {
1368 if (documentedFiles==0) return;
1369
1370 ol.pushGeneratorState();
1371 ol.disable(OutputGenerator::Man);
1372 ol.disable(OutputGenerator::Docbook);
1373
1374 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileList);
1375 if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files); // fall back
1376 QCString title = lne ? lne->title() : theTranslator->trFileList();
1377 bool addToIndex = lne==0 || lne->visible();
1378
1379 startFile(ol,"files",QCString(),title,HLI_Files);
1380 startTitle(ol,QCString());
1381 //if (!Config_getString(PROJECT_NAME).isEmpty())
1382 //{
1383 // title.prepend(Config_getString(PROJECT_NAME)+" ");
1384 //}
1385 ol.parseText(title);
1386 endTitle(ol,QCString(),QCString());
1387 ol.startContents();
1388 ol.startTextBlock();
1389
1390 if (addToIndex)
1391 {
1392 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"files",QCString(),TRUE,TRUE);
1393 Doxygen::indexList->incContentsDepth();
1394 }
1395
1396 ol.parseText(lne ? lne->intro() : theTranslator->trFileListDescription(Config_getBool(EXTRACT_ALL)));
1397 ol.endTextBlock();
1398
1399 // ---------------
1400 // Flat file index
1401 // ---------------
1402
1403 // 1. {
1404 ol.pushGeneratorState();
1405 ol.disable(OutputGenerator::Html);
1406
1407 ol.startIndexList();
1408 if (Config_getBool(FULL_PATH_NAMES))
1409 {
1410 std::unordered_map<std::string,size_t> pathMap;
1411 std::vector<FilesInDir> outputFiles;
1412
1413 // re-sort input files in (dir,file) output order instead of (file,dir) input order
1414 for (const auto &fn : *Doxygen::inputNameLinkedMap)
1415 {
1416 for (const auto &fd : *fn)
1417 {
1418 QCString path=fd->getPath();
1419 if (path.isEmpty()) path="[external]";
1420 auto it = pathMap.find(path.str());
1421 if (it!=pathMap.end()) // existing path -> append
1422 {
1423 outputFiles.at(it->second).files.push_back(fd.get());
1424 }
1425 else // new path -> create path entry + append
1426 {
1427 pathMap.insert(std::make_pair(path.str(),outputFiles.size()));
1428 outputFiles.emplace_back(path);
1429 outputFiles.back().files.push_back(fd.get());
1430 }
1431 }
1432 }
1433
1434 // sort the files by path
1435 std::sort(outputFiles.begin(),
1436 outputFiles.end(),
1437 [](const auto &fp1,const auto &fp2) { return qstricmp(fp1.path,fp2.path)<0; });
1438 // sort the files inside the directory by name
1439 for (auto &fp : outputFiles)
1440 {
1441 std::sort(fp.files.begin(), fp.files.end(), compareFileDefs);
1442 }
1443 // write the results
1444 for (const auto &fp : outputFiles)
1445 {
1446 for (const auto &fd : fp.files)
1447 {
1448 writeSingleFileIndex(ol,fd);
1449 }
1450 }
1451 }
1452 else
1453 {
1454 for (const auto &fn : *Doxygen::inputNameLinkedMap)
1455 {
1456 for (const auto &fd : *fn)
1457 {
1458 writeSingleFileIndex(ol,fd.get());
1459 }
1460 }
1461 }
1462 ol.endIndexList();
1463
1464 // 1. }
1465 ol.popGeneratorState();
1466
1467 // ---------------
1468 // Hierarchical file index for HTML
1469 // ---------------
1470 ol.pushGeneratorState();
1471 ol.disableAllBut(OutputGenerator::Html);
1472
1473 FTVHelp* ftv = new FTVHelp(FALSE);
1474 writeDirHierarchy(ol,ftv,addToIndex);
1475 TextStream t;
1476 ftv->generateTreeViewInline(t);
1477 ol.writeString(t.str().c_str());
1478 delete ftv;
1479
1480 ol.popGeneratorState();
1481 // ------
1482
1483 if (addToIndex)
1484 {
1485 Doxygen::indexList->decContentsDepth();
1486 }
1487
1488 endFile(ol);
1489 ol.popGeneratorState();
1490 }
1491
1492 //----------------------------------------------------------------------------
countNamespaces()1493 static int countNamespaces()
1494 {
1495 int count=0;
1496 for (const auto &nd : *Doxygen::namespaceLinkedMap)
1497 {
1498 if (nd->isLinkableInProject()) count++;
1499 }
1500 return count;
1501 }
1502
1503 //----------------------------------------------------------------------------
countConcepts()1504 static int countConcepts()
1505 {
1506 int count=0;
1507 for (const auto &cd : *Doxygen::conceptLinkedMap)
1508 {
1509 if (cd->isLinkableInProject()) count++;
1510 }
1511 return count;
1512 }
1513
1514
1515 //----------------------------------------------------------------------------
1516 template<typename Ptr> const ClassDef *get_pointer(const Ptr &p);
get_pointer(const ClassLinkedMap::Ptr & p)1517 template<> const ClassDef *get_pointer(const ClassLinkedMap::Ptr &p) { return p.get(); }
get_pointer(const ClassLinkedRefMap::Ptr & p)1518 template<> const ClassDef *get_pointer(const ClassLinkedRefMap::Ptr &p) { return p; }
1519
1520 template<class ListType>
writeClassTree(const ListType & cl,FTVHelp * ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct)1521 static void writeClassTree(const ListType &cl,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct)
1522 {
1523 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
1524 for (const auto &cdi : cl)
1525 {
1526 const ClassDef *cd = get_pointer(cdi);
1527 ClassDefMutable *cdm = toClassDefMutable(cd);
1528 if (cdm && cd->getLanguage()==SrcLangExt_VHDL)
1529 {
1530 if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
1531 (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS
1532 )// no architecture
1533 {
1534 continue;
1535 }
1536 if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS)
1537 {
1538 QCString n=cd->name();
1539 cdm->setClassName(n);
1540 }
1541 }
1542
1543 if (sliceOpt && cd->compoundType() != ct)
1544 {
1545 continue;
1546 }
1547
1548 if (!globalOnly ||
1549 cd->getOuterScope()==0 ||
1550 cd->getOuterScope()==Doxygen::globalScope
1551 )
1552 {
1553 int count=0;
1554 for (const auto &ccd : cd->getClasses())
1555 {
1556 if (ccd->isLinkableInProject() && ccd->templateMaster()==0)
1557 {
1558 count++;
1559 }
1560 }
1561 if (classVisibleInIndex(cd) && cd->templateMaster()==0)
1562 {
1563 ftv->addContentsItem(count>0,cd->displayName(FALSE),cd->getReference(),
1564 cd->getOutputFileBase(),cd->anchor(),FALSE,TRUE,cd);
1565 if (addToIndex &&
1566 (cd->getOuterScope()==0 ||
1567 cd->getOuterScope()->definitionType()!=Definition::TypeClass
1568 )
1569 )
1570 {
1571 addMembersToIndex(cd,LayoutDocManager::Class,
1572 cd->displayName(FALSE),
1573 cd->anchor(),
1574 cd->partOfGroups().empty() && !cd->isSimple());
1575 }
1576 if (count>0)
1577 {
1578 ftv->incContentsDepth();
1579 writeClassTree(cd->getClasses(),ftv,addToIndex,FALSE,ct);
1580 ftv->decContentsDepth();
1581 }
1582 }
1583 }
1584 }
1585 }
1586
countVisibleMembers(const NamespaceDef * nd)1587 int countVisibleMembers(const NamespaceDef *nd)
1588 {
1589 int count=0;
1590 for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace))
1591 {
1592 if (lde->kind()==LayoutDocEntry::MemberDef)
1593 {
1594 const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
1595 MemberList *ml = nd->getMemberList(lmd->type);
1596 if (ml)
1597 {
1598 for (const auto &md : *ml)
1599 {
1600 if (md->visibleInIndex())
1601 {
1602 count++;
1603 }
1604 }
1605 }
1606 }
1607 }
1608 return count;
1609 }
1610
writeNamespaceMembers(const NamespaceDef * nd,bool addToIndex)1611 static void writeNamespaceMembers(const NamespaceDef *nd,bool addToIndex)
1612 {
1613 for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace))
1614 {
1615 if (lde->kind()==LayoutDocEntry::MemberDef)
1616 {
1617 const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
1618 MemberList *ml = nd->getMemberList(lmd->type);
1619 if (ml)
1620 {
1621 for (const auto &md : *ml)
1622 {
1623 //printf(" member %s visible=%d\n",qPrint(md->name()),md->visibleInIndex());
1624 if (md->visibleInIndex())
1625 {
1626 writeMemberToIndex(nd,md,addToIndex);
1627 }
1628 }
1629 }
1630 }
1631 }
1632 }
1633
1634 static void writeConceptList(const ConceptLinkedRefMap &concepts, FTVHelp *ftv,bool addToIndex);
1635 static void writeNamespaceTree(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
1636 bool rootOnly,bool addToIndex);
1637
writeNamespaceTreeElement(const NamespaceDef * nd,FTVHelp * ftv,bool rootOnly,bool addToIndex)1638 static void writeNamespaceTreeElement(const NamespaceDef *nd,FTVHelp *ftv,
1639 bool rootOnly,bool addToIndex)
1640 {
1641 if (!nd->isAnonymous() &&
1642 (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
1643 {
1644
1645 bool hasChildren = namespaceHasNestedNamespace(nd) ||
1646 namespaceHasNestedClass(nd,false,ClassDef::Class) ||
1647 namespaceHasNestedConcept(nd);
1648 bool isLinkable = nd->isLinkableInProject();
1649 int visibleMembers = countVisibleMembers(nd);
1650
1651 //printf("namespace %s hasChildren=%d visibleMembers=%d\n",qPrint(nd->name()),hasChildren,visibleMembers);
1652
1653 QCString ref;
1654 QCString file;
1655 if (isLinkable)
1656 {
1657 ref = nd->getReference();
1658 file = nd->getOutputFileBase();
1659 if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK
1660 {
1661 file=file.replace(0,qstrlen("namespace"),"class");
1662 }
1663 }
1664
1665 bool isDir = hasChildren || visibleMembers>0;
1666 if ((isLinkable) || isDir)
1667 {
1668 ftv->addContentsItem(hasChildren,nd->localName(),ref,file,QCString(),FALSE,nd->partOfGroups().empty(),nd);
1669
1670 if (addToIndex)
1671 {
1672 Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(),
1673 hasChildren && !file.isEmpty(),nd->partOfGroups().empty());
1674 }
1675 if (addToIndex && isDir)
1676 {
1677 Doxygen::indexList->incContentsDepth();
1678 }
1679
1680 if (isDir)
1681 {
1682 ftv->incContentsDepth();
1683 writeNamespaceTree(nd->getNamespaces(),ftv,FALSE,addToIndex);
1684 writeClassTree(nd->getClasses(),ftv,addToIndex,FALSE,ClassDef::Class);
1685 writeConceptList(nd->getConcepts(),ftv,addToIndex);
1686 writeNamespaceMembers(nd,addToIndex);
1687 ftv->decContentsDepth();
1688 }
1689 if (addToIndex && isDir)
1690 {
1691 Doxygen::indexList->decContentsDepth();
1692 }
1693 }
1694 }
1695 }
1696
writeNamespaceTree(const NamespaceLinkedRefMap & nsLinkedMap,FTVHelp * ftv,bool rootOnly,bool addToIndex)1697 static void writeNamespaceTree(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
1698 bool rootOnly,bool addToIndex)
1699 {
1700 for (const auto &nd : nsLinkedMap)
1701 {
1702 writeNamespaceTreeElement(nd,ftv,rootOnly,addToIndex);
1703 }
1704 }
1705
writeNamespaceTree(const NamespaceLinkedMap & nsLinkedMap,FTVHelp * ftv,bool rootOnly,bool addToIndex)1706 static void writeNamespaceTree(const NamespaceLinkedMap &nsLinkedMap,FTVHelp *ftv,
1707 bool rootOnly,bool addToIndex)
1708 {
1709 for (const auto &nd : nsLinkedMap)
1710 {
1711 writeNamespaceTreeElement(nd.get(),ftv,rootOnly,addToIndex);
1712 }
1713 }
1714
1715 static void writeClassTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
1716 bool rootOnly,bool addToIndex,ClassDef::CompoundType ct);
1717
writeClassTreeInsideNamespaceElement(const NamespaceDef * nd,FTVHelp * ftv,bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)1718 static void writeClassTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv,
1719 bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)
1720 {
1721 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
1722 if (!nd->isAnonymous() &&
1723 (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
1724 {
1725 bool isDir = namespaceHasNestedClass(nd,sliceOpt,ct);
1726 bool isLinkable = nd->isLinkableInProject();
1727
1728 //printf("namespace %s isDir=%d\n",qPrint(nd->name()),isDir);
1729
1730 QCString ref;
1731 QCString file;
1732 if (isLinkable)
1733 {
1734 ref = nd->getReference();
1735 file = nd->getOutputFileBase();
1736 if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK
1737 {
1738 file=file.replace(0,qstrlen("namespace"),"class");
1739 }
1740 }
1741
1742 if (isDir)
1743 {
1744 ftv->addContentsItem(isDir,nd->localName(),ref,file,QCString(),FALSE,TRUE,nd);
1745
1746 if (addToIndex)
1747 {
1748 // the namespace entry is already shown under the namespace list so don't
1749 // add it to the nav index and don't create a separate index file for it otherwise
1750 // it will overwrite the one written for the namespace list.
1751 Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(),
1752 false, // separateIndex
1753 false // addToNavIndex
1754 );
1755 }
1756 if (addToIndex)
1757 {
1758 Doxygen::indexList->incContentsDepth();
1759 }
1760
1761 ftv->incContentsDepth();
1762 writeClassTreeInsideNamespace(nd->getNamespaces(),ftv,FALSE,addToIndex,ct);
1763 ClassLinkedRefMap d = nd->getClasses();
1764 if (sliceOpt)
1765 {
1766 if (ct == ClassDef::Interface)
1767 {
1768 d = nd->getInterfaces();
1769 }
1770 else if (ct == ClassDef::Struct)
1771 {
1772 d = nd->getStructs();
1773 }
1774 else if (ct == ClassDef::Exception)
1775 {
1776 d = nd->getExceptions();
1777 }
1778 }
1779 writeClassTree(d,ftv,addToIndex,FALSE,ct);
1780 ftv->decContentsDepth();
1781
1782 if (addToIndex)
1783 {
1784 Doxygen::indexList->decContentsDepth();
1785 }
1786 }
1787 }
1788 }
1789
writeClassTreeInsideNamespace(const NamespaceLinkedRefMap & nsLinkedMap,FTVHelp * ftv,bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)1790 static void writeClassTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
1791 bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)
1792 {
1793 for (const auto &nd : nsLinkedMap)
1794 {
1795 writeClassTreeInsideNamespaceElement(nd,ftv,rootOnly,addToIndex,ct);
1796 }
1797 }
1798
writeClassTreeInsideNamespace(const NamespaceLinkedMap & nsLinkedMap,FTVHelp * ftv,bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)1799 static void writeClassTreeInsideNamespace(const NamespaceLinkedMap &nsLinkedMap,FTVHelp *ftv,
1800 bool rootOnly,bool addToIndex,ClassDef::CompoundType ct)
1801 {
1802 for (const auto &nd : nsLinkedMap)
1803 {
1804 writeClassTreeInsideNamespaceElement(nd.get(),ftv,rootOnly,addToIndex,ct);
1805 }
1806 }
1807
writeNamespaceIndex(OutputList & ol)1808 static void writeNamespaceIndex(OutputList &ol)
1809 {
1810 if (documentedNamespaces==0) return;
1811 ol.pushGeneratorState();
1812 ol.disable(OutputGenerator::Man);
1813 ol.disable(OutputGenerator::Docbook);
1814 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceList);
1815 if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Namespaces); // fall back
1816 QCString title = lne ? lne->title() : theTranslator->trNamespaceList();
1817 bool addToIndex = lne==0 || lne->visible();
1818 startFile(ol,"namespaces",QCString(),title,HLI_Namespaces);
1819 startTitle(ol,QCString());
1820 ol.parseText(title);
1821 endTitle(ol,QCString(),QCString());
1822 ol.startContents();
1823 ol.startTextBlock();
1824 ol.parseText(lne ? lne->intro() : theTranslator->trNamespaceListDescription(Config_getBool(EXTRACT_ALL)));
1825 ol.endTextBlock();
1826
1827 bool first=TRUE;
1828
1829 // ---------------
1830 // Linear namespace index for Latex/RTF
1831 // ---------------
1832 ol.pushGeneratorState();
1833 ol.disable(OutputGenerator::Html);
1834
1835 for (const auto &nd : *Doxygen::namespaceLinkedMap)
1836 {
1837 if (nd->isLinkableInProject())
1838 {
1839 if (first)
1840 {
1841 ol.startIndexList();
1842 first=FALSE;
1843 }
1844 //ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name());
1845 ol.startIndexKey();
1846 if (nd->getLanguage()==SrcLangExt_VHDL)
1847 {
1848 ol.writeObjectLink(QCString(), nd->getOutputFileBase().replace(0,qstrlen("namespace"),"class"),QCString(),nd->displayName());
1849 }
1850 else
1851 {
1852 ol.writeObjectLink(QCString(),nd->getOutputFileBase(),QCString(),nd->displayName());
1853 }
1854 ol.endIndexKey();
1855
1856 bool hasBrief = !nd->briefDescription().isEmpty();
1857 ol.startIndexValue(hasBrief);
1858 if (hasBrief)
1859 {
1860 //ol.docify(" (");
1861 ol.generateDoc(
1862 nd->briefFile(),nd->briefLine(),
1863 nd.get(),0,
1864 nd->briefDescription(TRUE),
1865 FALSE, // index words
1866 FALSE, // isExample
1867 QCString(), // example name
1868 TRUE, // single line
1869 TRUE, // link from index
1870 Config_getBool(MARKDOWN_SUPPORT)
1871 );
1872 //ol.docify(")");
1873 }
1874 ol.endIndexValue(nd->getOutputFileBase(),hasBrief);
1875
1876 }
1877 }
1878 if (!first) ol.endIndexList();
1879
1880 ol.popGeneratorState();
1881
1882 // ---------------
1883 // Hierarchical namespace index for HTML
1884 // ---------------
1885 ol.pushGeneratorState();
1886 ol.disableAllBut(OutputGenerator::Html);
1887
1888 {
1889 if (addToIndex)
1890 {
1891 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"namespaces",QCString(),TRUE,TRUE);
1892 Doxygen::indexList->incContentsDepth();
1893 }
1894 FTVHelp* ftv = new FTVHelp(FALSE);
1895 writeNamespaceTree(*Doxygen::namespaceLinkedMap,ftv,TRUE,addToIndex);
1896 TextStream t;
1897 ftv->generateTreeViewInline(t);
1898 ol.writeString(t.str().c_str());
1899 delete ftv;
1900 if (addToIndex)
1901 {
1902 Doxygen::indexList->decContentsDepth();
1903 }
1904 }
1905
1906 ol.popGeneratorState();
1907 // ------
1908
1909 endFile(ol);
1910 ol.popGeneratorState();
1911 }
1912
1913 //----------------------------------------------------------------------------
1914
countAnnotatedClasses(int * cp,ClassDef::CompoundType ct)1915 static int countAnnotatedClasses(int *cp, ClassDef::CompoundType ct)
1916 {
1917 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
1918 int count=0;
1919 int countPrinted=0;
1920 for (const auto &cd : *Doxygen::classLinkedMap)
1921 {
1922 if (sliceOpt && cd->compoundType() != ct)
1923 {
1924 continue;
1925 }
1926 if (cd->isLinkableInProject() && cd->templateMaster()==0)
1927 {
1928 if (!cd->isEmbeddedInOuterScope())
1929 {
1930 countPrinted++;
1931 }
1932 count++;
1933 }
1934 }
1935 *cp = countPrinted;
1936 return count;
1937 }
1938
1939
writeAnnotatedClassList(OutputList & ol,ClassDef::CompoundType ct)1940 static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct)
1941 {
1942 //LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList);
1943 //bool addToIndex = lne==0 || lne->visible();
1944 bool first=TRUE;
1945
1946 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
1947
1948 for (const auto &cd : *Doxygen::classLinkedMap)
1949 {
1950 if (cd->getLanguage()==SrcLangExt_VHDL &&
1951 ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS ||
1952 (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS)
1953 ) // no architecture
1954 {
1955 continue;
1956 }
1957 if (first)
1958 {
1959 ol.startIndexList();
1960 first=FALSE;
1961 }
1962
1963 if (sliceOpt && cd->compoundType() != ct)
1964 {
1965 continue;
1966 }
1967
1968 ol.pushGeneratorState();
1969 if (cd->isEmbeddedInOuterScope())
1970 {
1971 ol.disable(OutputGenerator::Latex);
1972 ol.disable(OutputGenerator::Docbook);
1973 ol.disable(OutputGenerator::RTF);
1974 }
1975 if (cd->isLinkableInProject() && cd->templateMaster()==0)
1976 {
1977 ol.startIndexKey();
1978 if (cd->getLanguage()==SrcLangExt_VHDL)
1979 {
1980 QCString prot= VhdlDocGen::getProtectionName((VhdlDocGen::VhdlClasses)cd->protection());
1981 ol.docify(prot);
1982 ol.writeString(" ");
1983 }
1984 ol.writeObjectLink(QCString(),cd->getOutputFileBase(),cd->anchor(),cd->displayName());
1985 ol.endIndexKey();
1986 bool hasBrief = !cd->briefDescription().isEmpty();
1987 ol.startIndexValue(hasBrief);
1988 if (hasBrief)
1989 {
1990 ol.generateDoc(
1991 cd->briefFile(),cd->briefLine(),
1992 cd.get(),0,
1993 cd->briefDescription(TRUE),
1994 FALSE, // indexWords
1995 FALSE, // isExample
1996 QCString(), // example name
1997 TRUE, // single line
1998 TRUE, // link from index
1999 Config_getBool(MARKDOWN_SUPPORT)
2000 );
2001 }
2002 ol.endIndexValue(cd->getOutputFileBase(),hasBrief);
2003
2004 //if (addToIndex)
2005 //{
2006 // addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(),cd->anchor());
2007 //}
2008 }
2009 ol.popGeneratorState();
2010 }
2011 if (!first) ol.endIndexList();
2012 }
2013
isId1(int c)2014 inline bool isId1(int c)
2015 {
2016 return (c<127 && c>31); // printable ASCII character
2017 }
2018
letterToLabel(const QCString & startLetter)2019 static QCString letterToLabel(const QCString &startLetter)
2020 {
2021 if (startLetter.isEmpty()) return startLetter;
2022 const char *p = startLetter.data();
2023 char c = *p;
2024 QCString result;
2025 if (isId1(c))
2026 {
2027 result+=c;
2028 }
2029 else
2030 {
2031 result="0x";
2032 const char hex[]="0123456789abcdef";
2033 while ((c=*p++))
2034 {
2035 result+=hex[((unsigned char)c)>>4];
2036 result+=hex[((unsigned char)c)&0xf];
2037 }
2038 }
2039 return result;
2040 }
2041
2042 //----------------------------------------------------------------------------
2043
2044 /** Class representing a cell in the alphabetical class index. */
2045 class AlphaIndexTableCell
2046 {
2047 public:
AlphaIndexTableCell(int row,int col,const std::string & letter,const ClassDef * cd)2048 AlphaIndexTableCell(int row,int col,const std::string &letter,const ClassDef *cd) :
2049 m_letter(letter), m_class(cd), m_row(row), m_col(col)
2050 {
2051 }
2052
classDef() const2053 const ClassDef *classDef() const { return m_class; }
letter() const2054 std::string letter() const { return m_letter; }
row() const2055 int row() const { return m_row; }
column() const2056 int column() const { return m_col; }
2057
2058 private:
2059 std::string m_letter;
2060 const ClassDef *m_class;
2061 int m_row;
2062 int m_col;
2063 };
2064
2065 using UsedIndexLetters = std::set<std::string>;
2066
2067 // write an alphabetical index of all class with a header for each letter
writeAlphabeticalClassList(OutputList & ol,ClassDef::CompoundType ct,int annotatedCount)2068 static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct, int annotatedCount)
2069 {
2070 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
2071
2072 // What starting letters are used
2073 UsedIndexLetters indexLettersUsed;
2074
2075 // first count the number of headers
2076 for (const auto &cd : *Doxygen::classLinkedMap)
2077 {
2078 if (sliceOpt && cd->compoundType() != ct)
2079 continue;
2080 if (cd->isLinkableInProject() && cd->templateMaster()==0)
2081 {
2082 if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
2083 continue;
2084
2085 // get the first UTF8 character (after the part that should be ignored)
2086 int index = getPrefixIndex(cd->className());
2087 std::string letter = getUTF8CharAt(cd->className().str(),index);
2088 if (!letter.empty())
2089 {
2090 indexLettersUsed.insert(convertUTF8ToUpper(letter));
2091 }
2092 }
2093 }
2094
2095 // write quick link index (row of letters)
2096 QCString alphaLinks = "<div class=\"qindex\">";
2097 bool first=true;
2098 for (const auto &letter : indexLettersUsed)
2099 {
2100 if (!first) alphaLinks += " | ";
2101 first=false;
2102 QCString li = letterToLabel(letter.c_str());
2103 alphaLinks += "<a class=\"qindex\" href=\"#letter_" +
2104 li + "\">" +
2105 QCString(letter) + "</a>";
2106 }
2107 alphaLinks += "</div>\n";
2108 ol.writeString(alphaLinks);
2109
2110 std::map<std::string, std::vector<const ClassDef*> > classesByLetter;
2111
2112 // fill the columns with the class list (row elements in each column,
2113 // expect for the columns with number >= itemsInLastRow, which get one
2114 // item less.
2115 for (const auto &cd : *Doxygen::classLinkedMap)
2116 {
2117 if (sliceOpt && cd->compoundType() != ct)
2118 continue;
2119 if (cd->getLanguage()==SrcLangExt_VHDL && !((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ))// no architecture
2120 continue;
2121
2122 if (cd->isLinkableInProject() && cd->templateMaster()==0)
2123 {
2124 QCString className = cd->className();
2125 int index = getPrefixIndex(className);
2126 std::string letter = getUTF8CharAt(className.str(),index);
2127 if (!letter.empty())
2128 {
2129 letter = convertUTF8ToUpper(letter);
2130 auto it = classesByLetter.find(letter);
2131 if (it!=classesByLetter.end()) // add class to the existing list
2132 {
2133 it->second.push_back(cd.get());
2134 }
2135 else // new entry
2136 {
2137 classesByLetter.insert(
2138 std::make_pair(letter, std::vector<const ClassDef*>({ cd.get() })));
2139 }
2140 }
2141 }
2142 }
2143
2144 // sort the class lists per letter while ignoring the prefix
2145 for (auto &kv : classesByLetter)
2146 {
2147 std::sort(kv.second.begin(), kv.second.end(),
2148 [](const auto &c1,const auto &c2)
2149 {
2150 QCString n1 = c1->className();
2151 QCString n2 = c2->className();
2152 return qstricmp(n1.data()+getPrefixIndex(n1), n2.data()+getPrefixIndex(n2))<0;
2153 });
2154 }
2155
2156 // generate table
2157 if (!classesByLetter.empty())
2158 {
2159 ol.writeString("<div class=\"classindex\">\n");
2160 int counter=0;
2161 for (const auto &cl : classesByLetter)
2162 {
2163 QCString parity = (counter++%2)==0 ? "even" : "odd";
2164 ol.writeString("<dl class=\"classindex " + parity + "\">\n");
2165
2166 // write character heading
2167 ol.writeString("<dt class=\"alphachar\">");
2168 QCString s = letterToLabel(cl.first.c_str());
2169 ol.writeString("<a id=\"letter_");
2170 ol.writeString(s);
2171 ol.writeString("\" name=\"letter_");
2172 ol.writeString(s);
2173 ol.writeString("\">");
2174 ol.writeString(cl.first.c_str());
2175 ol.writeString("</a>");
2176 ol.writeString("</dt>\n");
2177
2178 // write class links
2179 for (const auto &cd : cl.second)
2180 {
2181 ol.writeString("<dd>");
2182 QCString namesp,cname;
2183 extractNamespaceName(cd->name(),cname,namesp);
2184 QCString nsDispName;
2185 SrcLangExt lang = cd->getLanguage();
2186 QCString sep = getLanguageSpecificSeparator(lang);
2187 if (sep!="::")
2188 {
2189 nsDispName=substitute(namesp,"::",sep);
2190 cname=substitute(cname,"::",sep);
2191 }
2192 else
2193 {
2194 nsDispName=namesp;
2195 }
2196
2197 ol.writeObjectLink(cd->getReference(),
2198 cd->getOutputFileBase(),cd->anchor(),cname);
2199 if (!namesp.isEmpty())
2200 {
2201 ol.writeString(" (");
2202 NamespaceDef *nd = getResolvedNamespace(namesp);
2203 if (nd && nd->isLinkable())
2204 {
2205 ol.writeObjectLink(nd->getReference(),
2206 nd->getOutputFileBase(),QCString(),nsDispName);
2207 }
2208 else
2209 {
2210 ol.docify(nsDispName);
2211 }
2212 ol.writeString(")");
2213 }
2214 ol.writeString("</dd>");
2215 }
2216
2217 ol.writeString("</dl>\n");
2218 }
2219 ol.writeString("</div>\n");
2220 }
2221 }
2222
2223 //----------------------------------------------------------------------------
2224
writeAlphabeticalIndex(OutputList & ol)2225 static void writeAlphabeticalIndex(OutputList &ol)
2226 {
2227 if (annotatedClasses==0) return;
2228 ol.pushGeneratorState();
2229 ol.disableAllBut(OutputGenerator::Html);
2230 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassIndex);
2231 QCString title = lne ? lne->title() : theTranslator->trCompoundIndex();
2232 bool addToIndex = lne==0 || lne->visible();
2233
2234 startFile(ol,"classes",QCString(),title,HLI_Classes);
2235
2236 startTitle(ol,QCString());
2237 ol.parseText(title);
2238 endTitle(ol,QCString(),QCString());
2239
2240 if (addToIndex)
2241 {
2242 Doxygen::indexList->addContentsItem(FALSE,title,QCString(),"classes",QCString(),FALSE,TRUE);
2243 }
2244
2245 ol.startContents();
2246 writeAlphabeticalClassList(ol, ClassDef::Class, annotatedClasses);
2247 endFile(ol); // contains ol.endContents()
2248
2249 ol.popGeneratorState();
2250 }
2251
2252 //----------------------------------------------------------------------------
2253
writeAlphabeticalInterfaceIndex(OutputList & ol)2254 static void writeAlphabeticalInterfaceIndex(OutputList &ol)
2255 {
2256 if (annotatedInterfaces==0) return;
2257 ol.pushGeneratorState();
2258 ol.disableAllBut(OutputGenerator::Html);
2259 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceIndex);
2260 QCString title = lne ? lne->title() : theTranslator->trInterfaceIndex();
2261 bool addToIndex = lne==0 || lne->visible();
2262
2263 startFile(ol,"interfaces",QCString(),title,HLI_Interfaces);
2264
2265 startTitle(ol,QCString());
2266 ol.parseText(title);
2267 endTitle(ol,QCString(),QCString());
2268
2269 if (addToIndex)
2270 {
2271 Doxygen::indexList->addContentsItem(FALSE,title,QCString(),"interfaces",QCString(),FALSE,TRUE);
2272 }
2273
2274 ol.startContents();
2275 writeAlphabeticalClassList(ol, ClassDef::Interface, annotatedInterfaces);
2276 endFile(ol); // contains ol.endContents()
2277
2278 ol.popGeneratorState();
2279 }
2280
2281 //----------------------------------------------------------------------------
2282
writeAlphabeticalStructIndex(OutputList & ol)2283 static void writeAlphabeticalStructIndex(OutputList &ol)
2284 {
2285 if (annotatedStructs==0) return;
2286 ol.pushGeneratorState();
2287 ol.disableAllBut(OutputGenerator::Html);
2288 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::StructIndex);
2289 QCString title = lne ? lne->title() : theTranslator->trStructIndex();
2290 bool addToIndex = lne==0 || lne->visible();
2291
2292 startFile(ol,"structs",QCString(),title,HLI_Structs);
2293
2294 startTitle(ol,QCString());
2295 ol.parseText(title);
2296 endTitle(ol,QCString(),QCString());
2297
2298 if (addToIndex)
2299 {
2300 Doxygen::indexList->addContentsItem(FALSE,title,QCString(),"structs",QCString(),FALSE,TRUE);
2301 }
2302
2303 ol.startContents();
2304 writeAlphabeticalClassList(ol, ClassDef::Struct, annotatedStructs);
2305 endFile(ol); // contains ol.endContents()
2306
2307 ol.popGeneratorState();
2308 }
2309
2310 //----------------------------------------------------------------------------
2311
writeAlphabeticalExceptionIndex(OutputList & ol)2312 static void writeAlphabeticalExceptionIndex(OutputList &ol)
2313 {
2314 if (annotatedExceptions==0) return;
2315 ol.pushGeneratorState();
2316 ol.disableAllBut(OutputGenerator::Html);
2317 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionIndex);
2318 QCString title = lne ? lne->title() : theTranslator->trExceptionIndex();
2319 bool addToIndex = lne==0 || lne->visible();
2320
2321 startFile(ol,"exceptions",QCString(),title,HLI_Exceptions);
2322
2323 startTitle(ol,QCString());
2324 ol.parseText(title);
2325 endTitle(ol,QCString(),QCString());
2326
2327 if (addToIndex)
2328 {
2329 Doxygen::indexList->addContentsItem(FALSE,title,QCString(),"exceptions",QCString(),FALSE,TRUE);
2330 }
2331
2332 ol.startContents();
2333 writeAlphabeticalClassList(ol, ClassDef::Exception, annotatedExceptions);
2334 endFile(ol); // contains ol.endContents()
2335
2336 ol.popGeneratorState();
2337 }
2338
2339 //----------------------------------------------------------------------------
2340
2341 struct AnnotatedIndexContext
2342 {
AnnotatedIndexContextAnnotatedIndexContext2343 AnnotatedIndexContext(int numAnno,int numPrint,
2344 LayoutNavEntry::Kind lk,LayoutNavEntry::Kind fk,
2345 const QCString &title,const QCString &intro,
2346 ClassDef::CompoundType ct,
2347 const QCString &fn,
2348 HighlightedItem hi) :
2349 numAnnotated(numAnno), numPrinted(numPrint),
2350 listKind(lk), fallbackKind(fk),
2351 listDefaultTitleText(title), listDefaultIntroText(intro),
2352 compoundType(ct),fileBaseName(fn),
2353 hiItem(hi) { }
2354
2355 const int numAnnotated;
2356 const int numPrinted;
2357 const LayoutNavEntry::Kind listKind;
2358 const LayoutNavEntry::Kind fallbackKind;
2359 const QCString listDefaultTitleText;
2360 const QCString listDefaultIntroText;
2361 const ClassDef::CompoundType compoundType;
2362 const QCString fileBaseName;
2363 const HighlightedItem hiItem;
2364 };
2365
writeAnnotatedIndexGeneric(OutputList & ol,const AnnotatedIndexContext ctx)2366 static void writeAnnotatedIndexGeneric(OutputList &ol,const AnnotatedIndexContext ctx)
2367 {
2368 //printf("writeAnnotatedIndex: count=%d printed=%d\n",
2369 // annotatedClasses,annotatedClassesPrinted);
2370 if (ctx.numAnnotated==0) return;
2371
2372 ol.pushGeneratorState();
2373 ol.disable(OutputGenerator::Man);
2374 if (ctx.numPrinted==0)
2375 {
2376 ol.disable(OutputGenerator::Latex);
2377 ol.disable(OutputGenerator::RTF);
2378 }
2379 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.listKind);
2380 if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.fallbackKind); // fall back
2381 QCString title = lne ? lne->title() : ctx.listDefaultTitleText;
2382 bool addToIndex = lne==0 || lne->visible();
2383
2384 startFile(ol,ctx.fileBaseName,QCString(),title,ctx.hiItem);
2385
2386 startTitle(ol,QCString());
2387 ol.parseText(title);
2388 endTitle(ol,QCString(),QCString());
2389
2390 ol.startContents();
2391
2392 ol.startTextBlock();
2393 ol.parseText(lne ? lne->intro() : ctx.listDefaultIntroText);
2394 ol.endTextBlock();
2395
2396 // ---------------
2397 // Linear class index for Latex/RTF
2398 // ---------------
2399 ol.pushGeneratorState();
2400 ol.disable(OutputGenerator::Html);
2401 Doxygen::indexList->disable();
2402
2403 writeAnnotatedClassList(ol, ctx.compoundType);
2404
2405 Doxygen::indexList->enable();
2406 ol.popGeneratorState();
2407
2408 // ---------------
2409 // Hierarchical class index for HTML
2410 // ---------------
2411 ol.pushGeneratorState();
2412 ol.disableAllBut(OutputGenerator::Html);
2413
2414 {
2415 if (addToIndex)
2416 {
2417 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),ctx.fileBaseName,QCString(),TRUE,TRUE);
2418 Doxygen::indexList->incContentsDepth();
2419 }
2420 FTVHelp ftv(false);
2421 writeClassTreeInsideNamespace(*Doxygen::namespaceLinkedMap,&ftv,TRUE,addToIndex,ctx.compoundType);
2422 writeClassTree(*Doxygen::classLinkedMap,&ftv,addToIndex,TRUE,ctx.compoundType);
2423 TextStream t;
2424 ftv.generateTreeViewInline(t);
2425 ol.writeString(t.str().c_str());
2426 if (addToIndex)
2427 {
2428 Doxygen::indexList->decContentsDepth();
2429 }
2430 }
2431
2432 ol.popGeneratorState();
2433 // ------
2434
2435 endFile(ol); // contains ol.endContents()
2436 ol.popGeneratorState();
2437 }
2438
2439 //----------------------------------------------------------------------------
2440
writeAnnotatedIndex(OutputList & ol)2441 static void writeAnnotatedIndex(OutputList &ol)
2442 {
2443 writeAnnotatedIndexGeneric(ol,
2444 AnnotatedIndexContext(annotatedClasses,annotatedClassesPrinted,
2445 LayoutNavEntry::ClassList,LayoutNavEntry::Classes,
2446 theTranslator->trCompoundList(),theTranslator->trCompoundListDescription(),
2447 ClassDef::Class,
2448 "annotated",
2449 HLI_AnnotatedClasses));
2450
2451 }
2452
2453 //----------------------------------------------------------------------------
2454
writeAnnotatedInterfaceIndex(OutputList & ol)2455 static void writeAnnotatedInterfaceIndex(OutputList &ol)
2456 {
2457 writeAnnotatedIndexGeneric(ol,
2458 AnnotatedIndexContext(annotatedInterfaces,annotatedInterfacesPrinted,
2459 LayoutNavEntry::InterfaceList,LayoutNavEntry::Interfaces,
2460 theTranslator->trInterfaceList(),theTranslator->trInterfaceListDescription(),
2461 ClassDef::Interface,
2462 "annotatedinterfaces",
2463 HLI_AnnotatedInterfaces));
2464
2465 }
2466
2467 //----------------------------------------------------------------------------
2468
writeAnnotatedStructIndex(OutputList & ol)2469 static void writeAnnotatedStructIndex(OutputList &ol)
2470 {
2471 writeAnnotatedIndexGeneric(ol,
2472 AnnotatedIndexContext(annotatedStructs,annotatedStructsPrinted,
2473 LayoutNavEntry::StructList,LayoutNavEntry::Structs,
2474 theTranslator->trStructList(),theTranslator->trStructListDescription(),
2475 ClassDef::Struct,
2476 "annotatedstructs",
2477 HLI_AnnotatedStructs));
2478
2479 }
2480
2481 //----------------------------------------------------------------------------
2482
writeAnnotatedExceptionIndex(OutputList & ol)2483 static void writeAnnotatedExceptionIndex(OutputList &ol)
2484 {
2485 writeAnnotatedIndexGeneric(ol,
2486 AnnotatedIndexContext(annotatedExceptions,annotatedExceptionsPrinted,
2487 LayoutNavEntry::ExceptionList,LayoutNavEntry::Exceptions,
2488 theTranslator->trExceptionList(),theTranslator->trExceptionListDescription(),
2489 ClassDef::Exception,
2490 "annotatedexceptions",
2491 HLI_AnnotatedExceptions));
2492
2493 }
2494
2495 //----------------------------------------------------------------------------
writeClassLinkForMember(OutputList & ol,const MemberDef * md,const QCString & separator,QCString & prevClassName)2496 static void writeClassLinkForMember(OutputList &ol,const MemberDef *md,const QCString &separator,
2497 QCString &prevClassName)
2498 {
2499 const ClassDef *cd=md->getClassDef();
2500 if ( cd && prevClassName!=cd->displayName())
2501 {
2502 ol.writeString(separator);
2503 ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2504 cd->displayName());
2505 //ol.writeString("\n");
2506 prevClassName = cd->displayName();
2507 }
2508 }
2509
writeFileLinkForMember(OutputList & ol,const MemberDef * md,const QCString & separator,QCString & prevFileName)2510 static void writeFileLinkForMember(OutputList &ol,const MemberDef *md,const QCString &separator,
2511 QCString &prevFileName)
2512 {
2513 const FileDef *fd=md->getFileDef();
2514 if (fd && prevFileName!=fd->name())
2515 {
2516 ol.writeString(separator);
2517 ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2518 fd->name());
2519 //ol.writeString("\n");
2520 prevFileName = fd->name();
2521 }
2522 }
2523
writeNamespaceLinkForMember(OutputList & ol,const MemberDef * md,const QCString & separator,QCString & prevNamespaceName)2524 static void writeNamespaceLinkForMember(OutputList &ol,const MemberDef *md,const QCString &separator,
2525 QCString &prevNamespaceName)
2526 {
2527 const NamespaceDef *nd=md->getNamespaceDef();
2528 if (nd && prevNamespaceName!=nd->displayName())
2529 {
2530 ol.writeString(separator);
2531 ol.writeObjectLink(md->getReference(),md->getOutputFileBase(),md->anchor(),
2532 nd->displayName());
2533 //ol.writeString("\n");
2534 prevNamespaceName = nd->displayName();
2535 }
2536 }
2537
writeMemberList(OutputList & ol,bool useSections,const std::string & page,const MemberIndexMap & memberIndexMap,Definition::DefType type)2538 static void writeMemberList(OutputList &ol,bool useSections,const std::string &page,
2539 const MemberIndexMap &memberIndexMap,
2540 Definition::DefType type)
2541 {
2542 int index = (int)type;
2543 ASSERT(index<3);
2544
2545 typedef void (*writeLinkForMember_t)(OutputList &ol,const MemberDef *md,const QCString &separator,
2546 QCString &prevNamespaceName);
2547
2548 // each index tab has its own write function
2549 static writeLinkForMember_t writeLinkForMemberMap[3] =
2550 {
2551 &writeClassLinkForMember,
2552 &writeFileLinkForMember,
2553 &writeNamespaceLinkForMember
2554 };
2555 QCString prevName;
2556 QCString prevDefName;
2557 bool first=TRUE;
2558 bool firstSection=TRUE;
2559 bool firstItem=TRUE;
2560 const MemberIndexList *mil = 0;
2561 std::string letter;
2562 for (const auto &kv : memberIndexMap)
2563 {
2564 if (!page.empty()) // specific page mode
2565 {
2566 auto it = memberIndexMap.find(page);
2567 if (it != memberIndexMap.end())
2568 {
2569 mil = &it->second;
2570 letter = page;
2571 }
2572 }
2573 else // do all pages
2574 {
2575 mil = &kv.second;
2576 letter = kv.first;
2577 }
2578 if (mil==0 || mil->empty()) continue;
2579 for (const auto &md : *mil)
2580 {
2581 const char *sep;
2582 bool isFunc=!md->isObjCMethod() &&
2583 (md->isFunction() || md->isSlot() || md->isSignal());
2584 QCString name=md->name();
2585 int startIndex = getPrefixIndex(name);
2586 if (name.data()+startIndex!=prevName) // new entry
2587 {
2588 if ((prevName.isEmpty() ||
2589 tolower(name.at(startIndex))!=tolower(prevName.at(0))) &&
2590 useSections) // new section
2591 {
2592 if (!firstItem) ol.endItemListItem();
2593 if (!firstSection) ol.endItemList();
2594 QCString cs = letterToLabel(letter.c_str());
2595 QCString anchor=(QCString)"index_"+convertToId(cs);
2596 QCString title=(QCString)"- "+letter.c_str()+" -";
2597 ol.startSection(anchor,title,SectionType::Subsection);
2598 ol.docify(title);
2599 ol.endSection(anchor,SectionType::Subsection);
2600 ol.startItemList();
2601 firstSection=FALSE;
2602 firstItem=TRUE;
2603 }
2604 else if (!useSections && first)
2605 {
2606 ol.startItemList();
2607 first=FALSE;
2608 }
2609
2610 // member name
2611 if (!firstItem) ol.endItemListItem();
2612 ol.startItemListItem();
2613 firstItem=FALSE;
2614 ol.docify(name);
2615 if (isFunc) ol.docify("()");
2616 //ol.writeString("\n");
2617
2618 // link to class
2619 prevDefName="";
2620 sep = " : ";
2621 prevName = name.data()+startIndex;
2622 }
2623 else // same entry
2624 {
2625 sep = ", ";
2626 // link to class for other members with the same name
2627 }
2628 if (index<3)
2629 {
2630 // write the link for the specific list type
2631 writeLinkForMemberMap[index](ol,md,sep,prevDefName);
2632 }
2633 }
2634 if (!page.empty())
2635 {
2636 break;
2637 }
2638 }
2639 if (!firstItem) ol.endItemListItem();
2640 ol.endItemList();
2641 }
2642
2643 //----------------------------------------------------------------------------
2644
initClassMemberIndices()2645 void initClassMemberIndices()
2646 {
2647 int j=0;
2648 for (j=0;j<CMHL_Total;j++)
2649 {
2650 documentedClassMembers[j]=0;
2651 g_classIndexLetterUsed[j].clear();
2652 }
2653 }
2654
addClassMemberNameToIndex(const MemberDef * md)2655 void addClassMemberNameToIndex(const MemberDef *md)
2656 {
2657 static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
2658 const ClassDef *cd=0;
2659
2660 if (md->isLinkableInProject() &&
2661 (cd=md->getClassDef()) &&
2662 cd->isLinkableInProject() &&
2663 cd->templateMaster()==0)
2664 {
2665 QCString n = md->name();
2666 int index = getPrefixIndex(n);
2667 std::string letter = getUTF8CharAt(n.str(),index);
2668 if (!letter.empty())
2669 {
2670 letter = convertUTF8ToLower(letter);
2671 bool isFriendToHide = hideFriendCompounds &&
2672 (QCString(md->typeString())=="friend class" ||
2673 QCString(md->typeString())=="friend struct" ||
2674 QCString(md->typeString())=="friend union");
2675 if (!(md->isFriend() && isFriendToHide) &&
2676 (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2677 )
2678 {
2679 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_All],letter,md);
2680 documentedClassMembers[CMHL_All]++;
2681 }
2682 if (md->isFunction() || md->isSlot() || md->isSignal())
2683 {
2684 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Functions],letter,md);
2685 documentedClassMembers[CMHL_Functions]++;
2686 }
2687 else if (md->isVariable())
2688 {
2689 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Variables],letter,md);
2690 documentedClassMembers[CMHL_Variables]++;
2691 }
2692 else if (md->isTypedef())
2693 {
2694 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Typedefs],letter,md);
2695 documentedClassMembers[CMHL_Typedefs]++;
2696 }
2697 else if (md->isEnumerate())
2698 {
2699 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Enums],letter,md);
2700 documentedClassMembers[CMHL_Enums]++;
2701 }
2702 else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2703 {
2704 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_EnumValues],letter,md);
2705 documentedClassMembers[CMHL_EnumValues]++;
2706 }
2707 else if (md->isProperty())
2708 {
2709 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Properties],letter,md);
2710 documentedClassMembers[CMHL_Properties]++;
2711 }
2712 else if (md->isEvent())
2713 {
2714 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Events],letter,md);
2715 documentedClassMembers[CMHL_Events]++;
2716 }
2717 else if (md->isRelated() || md->isForeign() ||
2718 (md->isFriend() && !isFriendToHide))
2719 {
2720 MemberIndexMap_add(g_classIndexLetterUsed[CMHL_Related],letter,md);
2721 documentedClassMembers[CMHL_Related]++;
2722 }
2723 }
2724 }
2725 }
2726
2727 //----------------------------------------------------------------------------
2728
initNamespaceMemberIndices()2729 void initNamespaceMemberIndices()
2730 {
2731 int j=0;
2732 for (j=0;j<NMHL_Total;j++)
2733 {
2734 documentedNamespaceMembers[j]=0;
2735 g_namespaceIndexLetterUsed[j].clear();
2736 }
2737 }
2738
addNamespaceMemberNameToIndex(const MemberDef * md)2739 void addNamespaceMemberNameToIndex(const MemberDef *md)
2740 {
2741 const NamespaceDef *nd=md->getNamespaceDef();
2742 if (nd && nd->isLinkableInProject() && md->isLinkableInProject())
2743 {
2744 QCString n = md->name();
2745 int index = getPrefixIndex(n);
2746 std::string letter = getUTF8CharAt(n.str(),index);
2747 if (!letter.empty())
2748 {
2749 letter = convertUTF8ToLower(letter);
2750 if (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2751 {
2752 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_All],letter,md);
2753 documentedNamespaceMembers[NMHL_All]++;
2754 }
2755
2756 if (md->isFunction())
2757 {
2758 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Functions],letter,md);
2759 documentedNamespaceMembers[NMHL_Functions]++;
2760 }
2761 else if (md->isVariable())
2762 {
2763 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Variables],letter,md);
2764 documentedNamespaceMembers[NMHL_Variables]++;
2765 }
2766 else if (md->isTypedef())
2767 {
2768 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Typedefs],letter,md);
2769 documentedNamespaceMembers[NMHL_Typedefs]++;
2770 }
2771 else if (md->isSequence())
2772 {
2773 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Sequences],letter,md);
2774 documentedNamespaceMembers[NMHL_Sequences]++;
2775 }
2776 else if (md->isDictionary())
2777 {
2778 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Dictionaries],letter,md);
2779 documentedNamespaceMembers[NMHL_Dictionaries]++;
2780 }
2781 else if (md->isEnumerate())
2782 {
2783 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_Enums],letter,md);
2784 documentedNamespaceMembers[NMHL_Enums]++;
2785 }
2786 else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2787 {
2788 MemberIndexMap_add(g_namespaceIndexLetterUsed[NMHL_EnumValues],letter,md);
2789 documentedNamespaceMembers[NMHL_EnumValues]++;
2790 }
2791 }
2792 }
2793 }
2794
2795 //----------------------------------------------------------------------------
2796
initFileMemberIndices()2797 void initFileMemberIndices()
2798 {
2799 int j=0;
2800 for (j=0;j<NMHL_Total;j++)
2801 {
2802 documentedFileMembers[j]=0;
2803 g_fileIndexLetterUsed[j].clear();
2804 }
2805 }
2806
addFileMemberNameToIndex(const MemberDef * md)2807 void addFileMemberNameToIndex(const MemberDef *md)
2808 {
2809 const FileDef *fd=md->getFileDef();
2810 if (fd && fd->isLinkableInProject() && md->isLinkableInProject())
2811 {
2812 QCString n = md->name();
2813 int index = getPrefixIndex(n);
2814 std::string letter = getUTF8CharAt(n.str(),index);
2815 if (!letter.empty())
2816 {
2817 letter = convertUTF8ToLower(letter);
2818 if (!md->isEnumValue() || (md->getEnumScope() && !md->getEnumScope()->isStrong()))
2819 {
2820 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_All],letter,md);
2821 documentedFileMembers[FMHL_All]++;
2822 }
2823
2824 if (md->isFunction())
2825 {
2826 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Functions],letter,md);
2827 documentedFileMembers[FMHL_Functions]++;
2828 }
2829 else if (md->isVariable())
2830 {
2831 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Variables],letter,md);
2832 documentedFileMembers[FMHL_Variables]++;
2833 }
2834 else if (md->isTypedef())
2835 {
2836 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Typedefs],letter,md);
2837 documentedFileMembers[FMHL_Typedefs]++;
2838 }
2839 else if (md->isSequence())
2840 {
2841 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Sequences],letter,md);
2842 documentedFileMembers[FMHL_Sequences]++;
2843 }
2844 else if (md->isDictionary())
2845 {
2846 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Dictionaries],letter,md);
2847 documentedFileMembers[FMHL_Dictionaries]++;
2848 }
2849 else if (md->isEnumerate())
2850 {
2851 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Enums],letter,md);
2852 documentedFileMembers[FMHL_Enums]++;
2853 }
2854 else if (md->isEnumValue() && md->getEnumScope() && !md->getEnumScope()->isStrong())
2855 {
2856 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_EnumValues],letter,md);
2857 documentedFileMembers[FMHL_EnumValues]++;
2858 }
2859 else if (md->isDefine())
2860 {
2861 MemberIndexMap_add(g_fileIndexLetterUsed[FMHL_Defines],letter,md);
2862 documentedFileMembers[FMHL_Defines]++;
2863 }
2864 }
2865 }
2866 }
2867
2868 //----------------------------------------------------------------------------
2869
sortMemberIndexList(MemberIndexMap & map)2870 static void sortMemberIndexList(MemberIndexMap &map)
2871 {
2872 for (auto &kv : map)
2873 {
2874 std::sort(kv.second.begin(),kv.second.end(),
2875 [](const MemberDef *md1,const MemberDef *md2)
2876 {
2877 int result = qstricmp(md1->name(),md2->name());
2878 return result==0 ? qstricmp(md1->qualifiedName(),md2->qualifiedName())<0 : result<0;
2879 });
2880 }
2881 }
2882
sortMemberIndexLists()2883 void sortMemberIndexLists()
2884 {
2885 for (auto &idx : g_classIndexLetterUsed)
2886 {
2887 sortMemberIndexList(idx);
2888 }
2889 for (auto &idx : g_fileIndexLetterUsed)
2890 {
2891 sortMemberIndexList(idx);
2892 }
2893 for (auto &idx : g_namespaceIndexLetterUsed)
2894 {
2895 sortMemberIndexList(idx);
2896 }
2897 }
2898
2899 //----------------------------------------------------------------------------
2900
writeQuickMemberIndex(OutputList & ol,const MemberIndexMap & map,const std::string & page,QCString fullName,bool multiPage)2901 static void writeQuickMemberIndex(OutputList &ol,
2902 const MemberIndexMap &map,const std::string &page,
2903 QCString fullName,bool multiPage)
2904 {
2905 bool first=TRUE;
2906 startQuickIndexList(ol,TRUE);
2907 for (const auto &kv : map)
2908 {
2909 QCString ci = kv.first.c_str();
2910 QCString is = letterToLabel(ci);
2911 QCString anchor;
2912 QCString extension=Doxygen::htmlFileExtension;
2913 if (!multiPage)
2914 anchor="#index_";
2915 else if (first)
2916 anchor=fullName+extension+"#index_";
2917 else
2918 anchor=fullName+"_"+is+extension+"#index_";
2919 startQuickIndexItem(ol,anchor+convertToId(is),kv.first==page,TRUE,first);
2920 ol.writeString(ci);
2921 endQuickIndexItem(ol);
2922 first=FALSE;
2923 }
2924 endQuickIndexList(ol);
2925 }
2926
2927 //----------------------------------------------------------------------------
2928
2929 /** Helper class representing a class member in the navigation menu. */
2930 struct CmhlInfo
2931 {
CmhlInfoCmhlInfo2932 CmhlInfo(const char *fn,const QCString &t) : fname(fn), title(t) {}
2933 const char *fname;
2934 QCString title;
2935 };
2936
getCmhlInfo(size_t hl)2937 static const CmhlInfo *getCmhlInfo(size_t hl)
2938 {
2939 static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
2940 static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
2941 static CmhlInfo cmhlInfo[] =
2942 {
2943 CmhlInfo("functions", theTranslator->trAll()),
2944 CmhlInfo("functions_func",
2945 fortranOpt ? theTranslator->trSubprograms() :
2946 vhdlOpt ? theTranslator->trFunctionAndProc() :
2947 theTranslator->trFunctions()),
2948 CmhlInfo("functions_vars",theTranslator->trVariables()),
2949 CmhlInfo("functions_type",theTranslator->trTypedefs()),
2950 CmhlInfo("functions_enum",theTranslator->trEnumerations()),
2951 CmhlInfo("functions_eval",theTranslator->trEnumerationValues()),
2952 CmhlInfo("functions_prop",theTranslator->trProperties()),
2953 CmhlInfo("functions_evnt",theTranslator->trEvents()),
2954 CmhlInfo("functions_rela",theTranslator->trRelatedFunctions())
2955 };
2956 return &cmhlInfo[hl];
2957 }
2958
writeClassMemberIndexFiltered(OutputList & ol,ClassMemberHighlight hl)2959 static void writeClassMemberIndexFiltered(OutputList &ol, ClassMemberHighlight hl)
2960 {
2961 if (documentedClassMembers[hl]==0) return;
2962
2963 static bool disableIndex = Config_getBool(DISABLE_INDEX);
2964
2965 bool multiPageIndex=FALSE;
2966 if (documentedClassMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
2967 {
2968 multiPageIndex=TRUE;
2969 }
2970
2971 ol.pushGeneratorState();
2972 ol.disableAllBut(OutputGenerator::Html);
2973
2974 QCString extension=Doxygen::htmlFileExtension;
2975 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassMembers);
2976 QCString title = lne ? lne->title() : theTranslator->trCompoundMembers();
2977 if (hl!=CMHL_All) title+=(QCString)" - "+getCmhlInfo(hl)->title;
2978 bool addToIndex = lne==0 || lne->visible();
2979
2980 if (addToIndex)
2981 {
2982 Doxygen::indexList->addContentsItem(multiPageIndex,getCmhlInfo(hl)->title,QCString(),
2983 getCmhlInfo(hl)->fname,QCString(),multiPageIndex,TRUE);
2984 if (multiPageIndex) Doxygen::indexList->incContentsDepth();
2985 }
2986
2987 bool first=TRUE;
2988 for (const auto &kv : g_classIndexLetterUsed[hl])
2989 {
2990 std::string page = kv.first;
2991 QCString fileName = getCmhlInfo(hl)->fname;
2992 if (multiPageIndex)
2993 {
2994 QCString cs(page);
2995 if (!first)
2996 {
2997 fileName+="_"+letterToLabel(cs);
2998 }
2999 if (addToIndex)
3000 {
3001 Doxygen::indexList->addContentsItem(FALSE,cs,QCString(),fileName,QCString(),FALSE,TRUE);
3002 }
3003 }
3004 bool quickIndex = documentedClassMembers[hl]>maxItemsBeforeQuickIndex;
3005
3006 ol.startFile(fileName+extension,QCString(),title);
3007 ol.startQuickIndices();
3008 if (!disableIndex)
3009 {
3010 ol.writeQuickLinks(TRUE,HLI_Functions,QCString());
3011
3012 if (!Config_getBool(HTML_DYNAMIC_MENUS))
3013 {
3014 startQuickIndexList(ol);
3015
3016 // index item for global member list
3017 startQuickIndexItem(ol,
3018 getCmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==CMHL_All,TRUE,first);
3019 ol.writeString(fixSpaces(getCmhlInfo(0)->title));
3020 endQuickIndexItem(ol);
3021
3022 int i;
3023 // index items per category member lists
3024 for (i=1;i<CMHL_Total;i++)
3025 {
3026 if (documentedClassMembers[i]>0)
3027 {
3028 startQuickIndexItem(ol,getCmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
3029 ol.writeString(fixSpaces(getCmhlInfo(i)->title));
3030 //printf("multiPageIndex=%d first=%d fileName=%s file=%s title=%s\n",
3031 // multiPageIndex,first,qPrint(fileName),getCmhlInfo(i)->fname,qPrint(getCmhlInfo(i)->title));
3032 endQuickIndexItem(ol);
3033 }
3034 }
3035
3036 endQuickIndexList(ol);
3037
3038 // quick alphabetical index
3039 if (quickIndex)
3040 {
3041 writeQuickMemberIndex(ol,g_classIndexLetterUsed[hl],page,
3042 getCmhlInfo(hl)->fname,multiPageIndex);
3043 }
3044 }
3045 }
3046 ol.endQuickIndices();
3047 ol.writeSplitBar(fileName);
3048 ol.writeSearchInfo();
3049
3050 ol.startContents();
3051
3052 if (hl==CMHL_All)
3053 {
3054 ol.startTextBlock();
3055 ol.parseText(lne ? lne->intro() : theTranslator->trCompoundMembersDescription(Config_getBool(EXTRACT_ALL)));
3056 ol.endTextBlock();
3057 }
3058 else
3059 {
3060 // hack to work around a mozilla bug, which refuses to switch to
3061 // normal lists otherwise
3062 ol.writeString(" ");
3063 }
3064
3065 writeMemberList(ol,quickIndex,
3066 multiPageIndex ? page : std::string(),
3067 g_classIndexLetterUsed[hl],
3068 Definition::TypeClass);
3069 endFile(ol);
3070 first=FALSE;
3071 }
3072
3073 if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
3074
3075 ol.popGeneratorState();
3076 }
3077
writeClassMemberIndex(OutputList & ol)3078 static void writeClassMemberIndex(OutputList &ol)
3079 {
3080 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassMembers);
3081 bool addToIndex = lne==0 || lne->visible();
3082
3083 if (documentedClassMembers[CMHL_All]>0 && addToIndex)
3084 {
3085 Doxygen::indexList->addContentsItem(TRUE,lne ? lne->title() : theTranslator->trCompoundMembers(),QCString(),"functions",QCString());
3086 Doxygen::indexList->incContentsDepth();
3087 }
3088 writeClassMemberIndexFiltered(ol,CMHL_All);
3089 writeClassMemberIndexFiltered(ol,CMHL_Functions);
3090 writeClassMemberIndexFiltered(ol,CMHL_Variables);
3091 writeClassMemberIndexFiltered(ol,CMHL_Typedefs);
3092 writeClassMemberIndexFiltered(ol,CMHL_Enums);
3093 writeClassMemberIndexFiltered(ol,CMHL_EnumValues);
3094 writeClassMemberIndexFiltered(ol,CMHL_Properties);
3095 writeClassMemberIndexFiltered(ol,CMHL_Events);
3096 writeClassMemberIndexFiltered(ol,CMHL_Related);
3097 if (documentedClassMembers[CMHL_All]>0 && addToIndex)
3098 {
3099 Doxygen::indexList->decContentsDepth();
3100 }
3101
3102 }
3103
3104 //----------------------------------------------------------------------------
3105
3106 /** Helper class representing a file member in the navigation menu. */
3107 struct FmhlInfo
3108 {
FmhlInfoFmhlInfo3109 FmhlInfo(const char *fn,const QCString &t) : fname(fn), title(t) {}
3110 const char *fname;
3111 QCString title;
3112 };
3113
getFmhlInfo(size_t hl)3114 static const FmhlInfo *getFmhlInfo(size_t hl)
3115 {
3116 static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
3117 static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
3118 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
3119 static FmhlInfo fmhlInfo[] =
3120 {
3121 FmhlInfo("globals", theTranslator->trAll()),
3122 FmhlInfo("globals_func",
3123 fortranOpt ? theTranslator->trSubprograms() :
3124 vhdlOpt ? theTranslator->trFunctionAndProc() :
3125 theTranslator->trFunctions()),
3126 FmhlInfo("globals_vars",sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()),
3127 FmhlInfo("globals_type",theTranslator->trTypedefs()),
3128 FmhlInfo("globals_sequ",theTranslator->trSequences()),
3129 FmhlInfo("globals_dict",theTranslator->trDictionaries()),
3130 FmhlInfo("globals_enum",theTranslator->trEnumerations()),
3131 FmhlInfo("globals_eval",theTranslator->trEnumerationValues()),
3132 FmhlInfo("globals_defs",theTranslator->trDefines())
3133 };
3134 return &fmhlInfo[hl];
3135 }
3136
writeFileMemberIndexFiltered(OutputList & ol,FileMemberHighlight hl)3137 static void writeFileMemberIndexFiltered(OutputList &ol, FileMemberHighlight hl)
3138 {
3139 if (documentedFileMembers[hl]==0) return;
3140
3141 static bool disableIndex = Config_getBool(DISABLE_INDEX);
3142
3143 bool multiPageIndex=FALSE;
3144 if (documentedFileMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
3145 {
3146 multiPageIndex=TRUE;
3147 }
3148
3149 ol.pushGeneratorState();
3150 ol.disableAllBut(OutputGenerator::Html);
3151
3152 QCString extension=Doxygen::htmlFileExtension;
3153 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileGlobals);
3154 QCString title = lne ? lne->title() : theTranslator->trFileMembers();
3155 bool addToIndex = lne==0 || lne->visible();
3156
3157 if (addToIndex)
3158 {
3159 Doxygen::indexList->addContentsItem(multiPageIndex,getFmhlInfo(hl)->title,QCString(),
3160 getFmhlInfo(hl)->fname,QCString(),multiPageIndex,TRUE);
3161 if (multiPageIndex) Doxygen::indexList->incContentsDepth();
3162 }
3163
3164 bool first=TRUE;
3165 for (const auto &kv : g_fileIndexLetterUsed[hl])
3166 {
3167 std::string page = kv.first;
3168 QCString fileName = getFmhlInfo(hl)->fname;
3169 if (multiPageIndex)
3170 {
3171 QCString cs(page);
3172 if (!first)
3173 {
3174 fileName+="_"+letterToLabel(cs);
3175 }
3176 if (addToIndex)
3177 {
3178 Doxygen::indexList->addContentsItem(FALSE,cs,QCString(),fileName,QCString(),FALSE,TRUE);
3179 }
3180 }
3181 bool quickIndex = documentedFileMembers[hl]>maxItemsBeforeQuickIndex;
3182
3183 ol.startFile(fileName+extension,QCString(),title);
3184 ol.startQuickIndices();
3185 if (!disableIndex)
3186 {
3187 ol.writeQuickLinks(TRUE,HLI_Globals,QCString());
3188 if (!Config_getBool(HTML_DYNAMIC_MENUS))
3189 {
3190 startQuickIndexList(ol);
3191
3192 // index item for all file member lists
3193 startQuickIndexItem(ol,
3194 getFmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==FMHL_All,TRUE,first);
3195 ol.writeString(fixSpaces(getFmhlInfo(0)->title));
3196 endQuickIndexItem(ol);
3197
3198 int i;
3199 // index items for per category member lists
3200 for (i=1;i<FMHL_Total;i++)
3201 {
3202 if (documentedFileMembers[i]>0)
3203 {
3204 startQuickIndexItem(ol,
3205 getFmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
3206 ol.writeString(fixSpaces(getFmhlInfo(i)->title));
3207 endQuickIndexItem(ol);
3208 }
3209 }
3210
3211 endQuickIndexList(ol);
3212
3213 if (quickIndex)
3214 {
3215 writeQuickMemberIndex(ol,g_fileIndexLetterUsed[hl],page,
3216 getFmhlInfo(hl)->fname,multiPageIndex);
3217 }
3218 }
3219 }
3220 ol.endQuickIndices();
3221 ol.writeSplitBar(fileName);
3222 ol.writeSearchInfo();
3223
3224 ol.startContents();
3225
3226 if (hl==FMHL_All)
3227 {
3228 ol.startTextBlock();
3229 ol.parseText(lne ? lne->intro() : theTranslator->trFileMembersDescription(Config_getBool(EXTRACT_ALL)));
3230 ol.endTextBlock();
3231 }
3232 else
3233 {
3234 // hack to work around a mozilla bug, which refuses to switch to
3235 // normal lists otherwise
3236 ol.writeString(" ");
3237 }
3238
3239 writeMemberList(ol,quickIndex,
3240 multiPageIndex ? page : std::string(),
3241 g_fileIndexLetterUsed[hl],
3242 Definition::TypeFile);
3243 endFile(ol);
3244 first=FALSE;
3245 }
3246 if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
3247 ol.popGeneratorState();
3248 }
3249
writeFileMemberIndex(OutputList & ol)3250 static void writeFileMemberIndex(OutputList &ol)
3251 {
3252 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileGlobals);
3253 bool addToIndex = lne==0 || lne->visible();
3254 if (documentedFileMembers[FMHL_All]>0 && addToIndex)
3255 {
3256 Doxygen::indexList->addContentsItem(FALSE,lne ? lne->title() : theTranslator->trFileMembers(),QCString(),"globals",QCString());
3257 Doxygen::indexList->incContentsDepth();
3258 }
3259 writeFileMemberIndexFiltered(ol,FMHL_All);
3260 writeFileMemberIndexFiltered(ol,FMHL_Functions);
3261 writeFileMemberIndexFiltered(ol,FMHL_Variables);
3262 writeFileMemberIndexFiltered(ol,FMHL_Typedefs);
3263 writeFileMemberIndexFiltered(ol,FMHL_Sequences);
3264 writeFileMemberIndexFiltered(ol,FMHL_Dictionaries);
3265 writeFileMemberIndexFiltered(ol,FMHL_Enums);
3266 writeFileMemberIndexFiltered(ol,FMHL_EnumValues);
3267 writeFileMemberIndexFiltered(ol,FMHL_Defines);
3268 if (documentedFileMembers[FMHL_All]>0 && addToIndex)
3269 {
3270 Doxygen::indexList->decContentsDepth();
3271 }
3272
3273 }
3274
3275 //----------------------------------------------------------------------------
3276
3277 /** Helper class representing a namespace member in the navigation menu. */
3278 struct NmhlInfo
3279 {
NmhlInfoNmhlInfo3280 NmhlInfo(const char *fn,const QCString &t) : fname(fn), title(t) {}
3281 const char *fname;
3282 QCString title;
3283 };
3284
getNmhlInfo(size_t hl)3285 static const NmhlInfo *getNmhlInfo(size_t hl)
3286 {
3287 static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
3288 static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
3289 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
3290 static NmhlInfo nmhlInfo[] =
3291 {
3292 NmhlInfo("namespacemembers", theTranslator->trAll()),
3293 NmhlInfo("namespacemembers_func",
3294 fortranOpt ? theTranslator->trSubprograms() :
3295 vhdlOpt ? theTranslator->trFunctionAndProc() :
3296 theTranslator->trFunctions()),
3297 NmhlInfo("namespacemembers_vars",sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables()),
3298 NmhlInfo("namespacemembers_type",theTranslator->trTypedefs()),
3299 NmhlInfo("namespacemembers_sequ",theTranslator->trSequences()),
3300 NmhlInfo("namespacemembers_dict",theTranslator->trDictionaries()),
3301 NmhlInfo("namespacemembers_enum",theTranslator->trEnumerations()),
3302 NmhlInfo("namespacemembers_eval",theTranslator->trEnumerationValues())
3303 };
3304 return &nmhlInfo[hl];
3305 }
3306
3307 //----------------------------------------------------------------------------
3308
writeNamespaceMemberIndexFiltered(OutputList & ol,NamespaceMemberHighlight hl)3309 static void writeNamespaceMemberIndexFiltered(OutputList &ol,
3310 NamespaceMemberHighlight hl)
3311 {
3312 if (documentedNamespaceMembers[hl]==0) return;
3313
3314 static bool disableIndex = Config_getBool(DISABLE_INDEX);
3315
3316
3317 bool multiPageIndex=FALSE;
3318 if (documentedNamespaceMembers[hl]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
3319 {
3320 multiPageIndex=TRUE;
3321 }
3322
3323 ol.pushGeneratorState();
3324 ol.disableAllBut(OutputGenerator::Html);
3325
3326 QCString extension=Doxygen::htmlFileExtension;
3327 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceMembers);
3328 QCString title = lne ? lne->title() : theTranslator->trNamespaceMembers();
3329 bool addToIndex = lne==0 || lne->visible();
3330
3331 if (addToIndex)
3332 {
3333 Doxygen::indexList->addContentsItem(multiPageIndex,getNmhlInfo(hl)->title,QCString(),
3334 getNmhlInfo(hl)->fname,QCString(),multiPageIndex,TRUE);
3335 if (multiPageIndex) Doxygen::indexList->incContentsDepth();
3336 }
3337
3338 bool first=TRUE;
3339 for (const auto &kv : g_namespaceIndexLetterUsed[hl])
3340 {
3341 std::string page = kv.first;
3342 QCString fileName = getNmhlInfo(hl)->fname;
3343 if (multiPageIndex)
3344 {
3345 QCString cs(page);
3346 if (!first)
3347 {
3348 fileName+="_"+letterToLabel(cs);
3349 }
3350 if (addToIndex)
3351 {
3352 Doxygen::indexList->addContentsItem(FALSE,cs,QCString(),fileName,QCString(),FALSE,TRUE);
3353 }
3354 }
3355 bool quickIndex = documentedNamespaceMembers[hl]>maxItemsBeforeQuickIndex;
3356
3357 ol.startFile(fileName+extension,QCString(),title);
3358 ol.startQuickIndices();
3359 if (!disableIndex)
3360 {
3361 ol.writeQuickLinks(TRUE,HLI_NamespaceMembers,QCString());
3362 if (!Config_getBool(HTML_DYNAMIC_MENUS))
3363 {
3364 startQuickIndexList(ol);
3365
3366 // index item for all namespace member lists
3367 startQuickIndexItem(ol,
3368 getNmhlInfo(0)->fname+Doxygen::htmlFileExtension,hl==NMHL_All,TRUE,first);
3369 ol.writeString(fixSpaces(getNmhlInfo(0)->title));
3370 endQuickIndexItem(ol);
3371
3372 int i;
3373 // index items per category member lists
3374 for (i=1;i<NMHL_Total;i++)
3375 {
3376 if (documentedNamespaceMembers[i]>0)
3377 {
3378 startQuickIndexItem(ol,
3379 getNmhlInfo(i)->fname+Doxygen::htmlFileExtension,hl==i,TRUE,first);
3380 ol.writeString(fixSpaces(getNmhlInfo(i)->title));
3381 endQuickIndexItem(ol);
3382 }
3383 }
3384
3385 endQuickIndexList(ol);
3386
3387 if (quickIndex)
3388 {
3389 writeQuickMemberIndex(ol,g_namespaceIndexLetterUsed[hl],page,
3390 getNmhlInfo(hl)->fname,multiPageIndex);
3391 }
3392 }
3393 }
3394 ol.endQuickIndices();
3395 ol.writeSplitBar(fileName);
3396 ol.writeSearchInfo();
3397
3398 ol.startContents();
3399
3400 if (hl==NMHL_All)
3401 {
3402 ol.startTextBlock();
3403 ol.parseText(lne ? lne->intro() : theTranslator->trNamespaceMemberDescription(Config_getBool(EXTRACT_ALL)));
3404 ol.endTextBlock();
3405 }
3406 else
3407 {
3408 // hack to work around a mozilla bug, which refuses to switch to
3409 // normal lists otherwise
3410 ol.writeString(" ");
3411 }
3412
3413 writeMemberList(ol,quickIndex,
3414 multiPageIndex ? page : std::string(),
3415 g_namespaceIndexLetterUsed[hl],
3416 Definition::TypeNamespace);
3417 endFile(ol);
3418 first=FALSE;
3419 }
3420 if (multiPageIndex && addToIndex) Doxygen::indexList->decContentsDepth();
3421 ol.popGeneratorState();
3422 }
3423
writeNamespaceMemberIndex(OutputList & ol)3424 static void writeNamespaceMemberIndex(OutputList &ol)
3425 {
3426 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceMembers);
3427 bool addToIndex = lne==0 || lne->visible();
3428 if (documentedNamespaceMembers[NMHL_All]>0 && addToIndex)
3429 {
3430 Doxygen::indexList->addContentsItem(FALSE,lne ? lne->title() : theTranslator->trNamespaceMembers(),QCString(),"namespacemembers",QCString());
3431 Doxygen::indexList->incContentsDepth();
3432 }
3433 //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
3434 writeNamespaceMemberIndexFiltered(ol,NMHL_All);
3435 writeNamespaceMemberIndexFiltered(ol,NMHL_Functions);
3436 writeNamespaceMemberIndexFiltered(ol,NMHL_Variables);
3437 writeNamespaceMemberIndexFiltered(ol,NMHL_Typedefs);
3438 writeNamespaceMemberIndexFiltered(ol,NMHL_Sequences);
3439 writeNamespaceMemberIndexFiltered(ol,NMHL_Dictionaries);
3440 writeNamespaceMemberIndexFiltered(ol,NMHL_Enums);
3441 writeNamespaceMemberIndexFiltered(ol,NMHL_EnumValues);
3442 if (documentedNamespaceMembers[NMHL_All]>0 && addToIndex)
3443 {
3444 Doxygen::indexList->decContentsDepth();
3445 }
3446
3447 }
3448
3449 //----------------------------------------------------------------------------
3450
3451 //----------------------------------------------------------------------------
3452
writeExampleIndex(OutputList & ol)3453 static void writeExampleIndex(OutputList &ol)
3454 {
3455 if (Doxygen::exampleLinkedMap->empty()) return;
3456 ol.pushGeneratorState();
3457 ol.disable(OutputGenerator::Man);
3458 ol.disable(OutputGenerator::Docbook);
3459 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Examples);
3460 QCString title = lne ? lne->title() : theTranslator->trExamples();
3461 bool addToIndex = lne==0 || lne->visible();
3462
3463 startFile(ol,"examples",QCString(),title,HLI_Examples);
3464
3465 startTitle(ol,QCString());
3466 ol.parseText(title);
3467 endTitle(ol,QCString(),QCString());
3468
3469 ol.startContents();
3470
3471 if (addToIndex)
3472 {
3473 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"examples",QCString(),TRUE,TRUE);
3474 Doxygen::indexList->incContentsDepth();
3475 }
3476
3477 ol.startTextBlock();
3478 ol.parseText(lne ? lne->intro() : theTranslator->trExamplesDescription());
3479 ol.endTextBlock();
3480
3481 ol.startItemList();
3482 for (const auto &pd : *Doxygen::exampleLinkedMap)
3483 {
3484 ol.startItemListItem();
3485 QCString n=pd->getOutputFileBase();
3486 if (!pd->title().isEmpty())
3487 {
3488 ol.writeObjectLink(QCString(),n,QCString(),pd->title());
3489 if (addToIndex)
3490 {
3491 Doxygen::indexList->addContentsItem(FALSE,filterTitle(pd->title().str()),pd->getReference(),n,QCString(),FALSE,TRUE);
3492 }
3493 }
3494 else
3495 {
3496 ol.writeObjectLink(QCString(),n,QCString(),pd->name());
3497 if (addToIndex)
3498 {
3499 Doxygen::indexList->addContentsItem(FALSE,pd->name(),pd->getReference(),n,QCString(),FALSE,TRUE);
3500 }
3501 }
3502 ol.endItemListItem();
3503 //ol.writeString("\n");
3504 }
3505 ol.endItemList();
3506
3507 if (addToIndex)
3508 {
3509 Doxygen::indexList->decContentsDepth();
3510 }
3511 endFile(ol);
3512 ol.popGeneratorState();
3513 }
3514
3515
3516 //----------------------------------------------------------------------------
3517
countRelatedPages(int & docPages,int & indexPages)3518 static void countRelatedPages(int &docPages,int &indexPages)
3519 {
3520 docPages=indexPages=0;
3521 for (const auto &pd : *Doxygen::pageLinkedMap)
3522 {
3523 if (pd->visibleInIndex())
3524 {
3525 indexPages++;
3526 }
3527 if (pd->documentedPage())
3528 {
3529 docPages++;
3530 }
3531 }
3532 }
3533
3534 //----------------------------------------------------------------------------
3535
mainPageHasOwnTitle()3536 static bool mainPageHasOwnTitle()
3537 {
3538 static QCString projectName = Config_getString(PROJECT_NAME);
3539 QCString title;
3540 if (Doxygen::mainPage)
3541 {
3542 title = filterTitle(Doxygen::mainPage->title().str());
3543 }
3544 return !projectName.isEmpty() && mainPageHasTitle() && qstricmp(title,projectName)!=0;
3545 }
3546
writePages(const PageDef * pd,FTVHelp * ftv)3547 static void writePages(const PageDef *pd,FTVHelp *ftv)
3548 {
3549 //printf("writePages()=%s pd=%p mainpage=%p\n",qPrint(pd->name()),pd,Doxygen::mainPage);
3550 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Pages);
3551 bool addToIndex = lne==0 || lne->visible();
3552 if (!addToIndex) return;
3553
3554 bool hasSubPages = pd->hasSubPages();
3555 bool hasSections = pd->hasSections();
3556
3557 if (pd->visibleInIndex())
3558 {
3559 QCString pageTitle;
3560
3561 if (pd->title().isEmpty())
3562 pageTitle=pd->name();
3563 else
3564 pageTitle=filterTitle(pd->title().str());
3565
3566 if (ftv)
3567 {
3568 //printf("*** adding %s hasSubPages=%d hasSections=%d\n",qPrint(pageTitle),hasSubPages,hasSections);
3569 ftv->addContentsItem(
3570 hasSubPages,pageTitle,
3571 pd->getReference(),pd->getOutputFileBase(),
3572 QCString(),hasSubPages,TRUE,pd);
3573 }
3574 if (addToIndex && pd!=Doxygen::mainPage.get())
3575 {
3576 Doxygen::indexList->addContentsItem(
3577 hasSubPages || hasSections,pageTitle,
3578 pd->getReference(),pd->getOutputFileBase(),
3579 QCString(),hasSubPages,TRUE);
3580 }
3581 }
3582 if (hasSubPages && ftv) ftv->incContentsDepth();
3583 bool doIndent = (hasSections || hasSubPages) &&
3584 (pd!=Doxygen::mainPage.get() || mainPageHasOwnTitle());
3585 if (doIndent)
3586 {
3587 Doxygen::indexList->incContentsDepth();
3588 }
3589 if (hasSections)
3590 {
3591 const_cast<PageDef*>(pd)->addSectionsToIndex();
3592 }
3593 for (const auto &subPage : pd->getSubPages())
3594 {
3595 writePages(subPage,ftv);
3596 }
3597 if (hasSubPages && ftv) ftv->decContentsDepth();
3598 if (doIndent)
3599 {
3600 Doxygen::indexList->decContentsDepth();
3601 }
3602 //printf("end writePages()=%s\n",qPrint(pd->title()));
3603 }
3604
3605 //----------------------------------------------------------------------------
3606
writePageIndex(OutputList & ol)3607 static void writePageIndex(OutputList &ol)
3608 {
3609 if (indexedPages==0) return;
3610 ol.pushGeneratorState();
3611 ol.disableAllBut(OutputGenerator::Html);
3612 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Pages);
3613 QCString title = lne ? lne->title() : theTranslator->trRelatedPages();
3614 startFile(ol,"pages",QCString(),title,HLI_Pages);
3615 startTitle(ol,QCString());
3616 ol.parseText(title);
3617 endTitle(ol,QCString(),QCString());
3618 ol.startContents();
3619 ol.startTextBlock();
3620 ol.parseText(lne ? lne->intro() : theTranslator->trRelatedPagesDescription());
3621 ol.endTextBlock();
3622
3623 {
3624 FTVHelp* ftv = new FTVHelp(FALSE);
3625 for (const auto &pd : *Doxygen::pageLinkedMap)
3626 {
3627 if ((pd->getOuterScope()==0 ||
3628 pd->getOuterScope()->definitionType()!=Definition::TypePage) && // not a sub page
3629 !pd->isReference() // not an external page
3630 )
3631 {
3632 writePages(pd.get(),ftv);
3633 }
3634 }
3635 TextStream t;
3636 ftv->generateTreeViewInline(t);
3637 ol.writeString(t.str().c_str());
3638 delete ftv;
3639 }
3640
3641 // ol.popGeneratorState();
3642 // ------
3643
3644 endFile(ol);
3645 ol.popGeneratorState();
3646 }
3647
3648 //----------------------------------------------------------------------------
3649
countGroups()3650 static int countGroups()
3651 {
3652 int count=0;
3653 for (const auto &gd : *Doxygen::groupLinkedMap)
3654 {
3655 if (!gd->isReference())
3656 {
3657 //gd->visited=FALSE;
3658 count++;
3659 }
3660 }
3661 return count;
3662 }
3663
3664 //----------------------------------------------------------------------------
3665
countDirs()3666 static int countDirs()
3667 {
3668 int count=0;
3669 for (const auto &dd : *Doxygen::dirLinkedMap)
3670 {
3671 if (dd->isLinkableInProject())
3672 {
3673 count++;
3674 }
3675 }
3676 return count;
3677 }
3678
3679
3680 //----------------------------------------------------------------------------
3681
writeGraphInfo(OutputList & ol)3682 void writeGraphInfo(OutputList &ol)
3683 {
3684 if (!Config_getBool(HAVE_DOT) || !Config_getBool(GENERATE_HTML)) return;
3685 ol.pushGeneratorState();
3686 ol.disableAllBut(OutputGenerator::Html);
3687
3688 DotLegendGraph gd;
3689 gd.writeGraph(Config_getString(HTML_OUTPUT));
3690
3691 bool stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS);
3692 bool oldStripCommentsState = stripCommentsStateRef;
3693 bool createSubdirs = Config_getBool(CREATE_SUBDIRS);
3694 bool oldCreateSubdirs = createSubdirs;
3695 // temporarily disable the stripping of comments for our own code example!
3696 stripCommentsStateRef = Config_updateBool(STRIP_CODE_COMMENTS,FALSE);
3697 // temporarily disable create subdirs for linking to our example
3698 createSubdirs = Config_updateBool(CREATE_SUBDIRS,FALSE);
3699
3700 startFile(ol,"graph_legend",QCString(),theTranslator->trLegendTitle());
3701 startTitle(ol,QCString());
3702 ol.parseText(theTranslator->trLegendTitle());
3703 endTitle(ol,QCString(),QCString());
3704 ol.startContents();
3705 QCString legendDocs = theTranslator->trLegendDocs();
3706 int s = legendDocs.find("<center>");
3707 int e = legendDocs.find("</center>");
3708 QCString imgExt = getDotImageExtension();
3709 if (imgExt=="svg" && s!=-1 && e!=-1)
3710 {
3711 legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e);
3712 //printf("legendDocs=%s\n",qPrint(legendDocs));
3713 }
3714 FileDef *fd = createFileDef("","graph_legend.dox");
3715 ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE,
3716 QCString(),FALSE,FALSE,FALSE);
3717 delete fd;
3718
3719 // restore config settings
3720 Config_updateBool(STRIP_CODE_COMMENTS,oldStripCommentsState);
3721 Config_updateBool(CREATE_SUBDIRS,oldCreateSubdirs);
3722
3723 endFile(ol);
3724 ol.popGeneratorState();
3725 }
3726
3727
3728
3729 //----------------------------------------------------------------------------
3730 /*!
3731 * write groups as hierarchical trees
3732 */
writeGroupTreeNode(OutputList & ol,const GroupDef * gd,int level,FTVHelp * ftv,bool addToIndex)3733 static void writeGroupTreeNode(OutputList &ol, const GroupDef *gd, int level, FTVHelp* ftv, bool addToIndex)
3734 {
3735 //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
3736 //bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
3737 if (level>20)
3738 {
3739 warn(gd->getDefFileName(),gd->getDefLine(),
3740 "maximum nesting level exceeded for group %s: check for possible recursive group relation!\n",qPrint(gd->name())
3741 );
3742 return;
3743 }
3744
3745 /* Some groups should appear twice under different parent-groups.
3746 * That is why we should not check if it was visited
3747 */
3748 if ((!gd->isASubGroup() || level>0) && gd->isVisible() &&
3749 (!gd->isReference() || Config_getBool(EXTERNAL_GROUPS)) // hide external groups by default
3750 )
3751 {
3752 //printf("gd->name()=%s #members=%d\n",qPrint(gd->name()),gd->countMembers());
3753 // write group info
3754 bool hasSubGroups = !gd->getSubGroups().empty();
3755 bool hasSubPages = !gd->getPages().empty();
3756 size_t numSubItems = 0;
3757 if (1 /*Config_getBool(TOC_EXPAND)*/)
3758 {
3759 for (const auto &ml : gd->getMemberLists())
3760 {
3761 if (ml->listType()&MemberListType_documentationLists)
3762 {
3763 numSubItems += ml->size();
3764 }
3765 }
3766 numSubItems += gd->getNamespaces().size();
3767 numSubItems += gd->getClasses().size();
3768 numSubItems += gd->getFiles().size();
3769 numSubItems += gd->getConcepts().size();
3770 numSubItems += gd->getDirs().size();
3771 numSubItems += gd->getPages().size();
3772 }
3773
3774 bool isDir = hasSubGroups || hasSubPages || numSubItems>0;
3775 //printf("gd='%s': pageDict=%d\n",qPrint(gd->name()),gd->pageDict->count());
3776 if (addToIndex)
3777 {
3778 Doxygen::indexList->addContentsItem(isDir,gd->groupTitle(),gd->getReference(),gd->getOutputFileBase(),QCString(),isDir,TRUE);
3779 Doxygen::indexList->incContentsDepth();
3780 }
3781 if (ftv)
3782 {
3783 ftv->addContentsItem(hasSubGroups,gd->groupTitle(),
3784 gd->getReference(),gd->getOutputFileBase(),QCString(),
3785 FALSE,FALSE,gd);
3786 ftv->incContentsDepth();
3787 }
3788
3789 //ol.writeListItem();
3790 //ol.startTextLink(gd->getOutputFileBase(),0);
3791 //parseText(ol,gd->groupTitle());
3792 //ol.endTextLink();
3793
3794 ol.startIndexListItem();
3795 ol.startIndexItem(gd->getReference(),gd->getOutputFileBase());
3796 ol.parseText(gd->groupTitle());
3797 ol.endIndexItem(gd->getReference(),gd->getOutputFileBase());
3798 if (gd->isReference())
3799 {
3800 ol.startTypewriter();
3801 ol.docify(" [external]");
3802 ol.endTypewriter();
3803 }
3804
3805 for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Group))
3806 {
3807 if (lde->kind()==LayoutDocEntry::MemberDef && addToIndex)
3808 {
3809 const LayoutDocEntryMemberDef *lmd = (const LayoutDocEntryMemberDef*)lde.get();
3810 MemberList *ml = gd->getMemberList(lmd->type);
3811 if (ml)
3812 {
3813 for (const auto &md : *ml)
3814 {
3815 const MemberVector &enumList = md->enumFieldList();
3816 isDir = !enumList.empty() && md->isEnumerate();
3817 if (md->isVisible() && !md->isAnonymous())
3818 {
3819 Doxygen::indexList->addContentsItem(isDir,
3820 md->qualifiedName(),md->getReference(),
3821 md->getOutputFileBase(),md->anchor(),FALSE,addToIndex);
3822 }
3823 if (isDir)
3824 {
3825 Doxygen::indexList->incContentsDepth();
3826 for (const auto &emd : enumList)
3827 {
3828 if (emd->isVisible())
3829 {
3830 Doxygen::indexList->addContentsItem(FALSE,
3831 emd->qualifiedName(),emd->getReference(),emd->getOutputFileBase(),
3832 emd->anchor(),FALSE,addToIndex);
3833 }
3834 }
3835 Doxygen::indexList->decContentsDepth();
3836 }
3837 }
3838 }
3839 }
3840 else if (lde->kind()==LayoutDocEntry::GroupClasses && addToIndex)
3841 {
3842 for (const auto &cd : gd->getClasses())
3843 {
3844 //bool nestedClassInSameGroup =
3845 // cd->getOuterScope() && cd->getOuterScope()->definitionType()==Definition::TypeClass &&
3846 // cd->getOuterScope()->partOfGroups().empty() && cd->getOuterScope()->partOfGroups()->contains(gd);
3847 //printf("===== GroupClasses: %s visible=%d nestedClassInSameGroup=%d\n",qPrint(cd->name()),cd->isVisible(),nestedClassInSameGroup);
3848 if (cd->isVisible() /*&& !nestedClassInSameGroup*/)
3849 {
3850 addMembersToIndex(cd,
3851 LayoutDocManager::Class,
3852 cd->displayName(),
3853 cd->anchor(),
3854 addToIndex,
3855 TRUE);
3856 }
3857 }
3858 }
3859 else if (lde->kind()==LayoutDocEntry::GroupNamespaces && addToIndex)
3860 {
3861 for (const auto &nd : gd->getNamespaces())
3862 {
3863 if (nd->isVisible())
3864 {
3865 Doxygen::indexList->addContentsItem(FALSE,
3866 nd->displayName(),nd->getReference(),
3867 nd->getOutputFileBase(),QCString(),FALSE,addToIndex);
3868 }
3869 }
3870 }
3871 else if (lde->kind()==LayoutDocEntry::GroupConcepts && addToIndex)
3872 {
3873 for (const auto &cd : gd->getConcepts())
3874 {
3875 if (cd->isVisible())
3876 {
3877 Doxygen::indexList->addContentsItem(FALSE,
3878 cd->displayName(),cd->getReference(),
3879 cd->getOutputFileBase(),QCString(),FALSE,addToIndex);
3880 }
3881 }
3882 }
3883 else if (lde->kind()==LayoutDocEntry::GroupFiles && addToIndex)
3884 {
3885 for (const auto &fd : gd->getFiles())
3886 {
3887 if (fd->isVisible())
3888 {
3889 Doxygen::indexList->addContentsItem(FALSE,
3890 fd->displayName(),fd->getReference(),
3891 fd->getOutputFileBase(),QCString(),FALSE,FALSE);
3892 }
3893 }
3894 }
3895 else if (lde->kind()==LayoutDocEntry::GroupDirs && addToIndex)
3896 {
3897 for (const auto &dd : gd->getDirs())
3898 {
3899 if (dd->isVisible())
3900 {
3901 Doxygen::indexList->addContentsItem(FALSE,
3902 dd->shortName(),dd->getReference(),
3903 dd->getOutputFileBase(),QCString(),FALSE,FALSE);
3904 }
3905 }
3906 }
3907 else if (lde->kind()==LayoutDocEntry::GroupPageDocs && addToIndex)
3908 {
3909 for (const auto &pd : gd->getPages())
3910 {
3911 const SectionInfo *si=0;
3912 if (!pd->name().isEmpty()) si=SectionManager::instance().find(pd->name());
3913 hasSubPages = pd->hasSubPages();
3914 bool hasSections = pd->hasSections();
3915 Doxygen::indexList->addContentsItem(
3916 hasSubPages || hasSections,
3917 pd->title(),
3918 gd->getReference(),
3919 gd->getOutputFileBase(),
3920 si ? si->label() : QCString(),
3921 hasSubPages || hasSections,
3922 TRUE); // addToNavIndex
3923 if (hasSections || hasSubPages)
3924 {
3925 Doxygen::indexList->incContentsDepth();
3926 }
3927 if (hasSections)
3928 {
3929 const_cast<PageDef*>(pd)->addSectionsToIndex();
3930 }
3931 writePages(pd,0);
3932 if (hasSections || hasSubPages)
3933 {
3934 Doxygen::indexList->decContentsDepth();
3935 }
3936 }
3937 }
3938 else if (lde->kind()==LayoutDocEntry::GroupNestedGroups)
3939 {
3940 if (!gd->getSubGroups().empty())
3941 {
3942 startIndexHierarchy(ol,level+1);
3943 for (const auto &subgd : gd->getSubGroups())
3944 {
3945 writeGroupTreeNode(ol,subgd,level+1,ftv,addToIndex);
3946 }
3947 endIndexHierarchy(ol,level+1);
3948 }
3949 }
3950 }
3951
3952 ol.endIndexListItem();
3953
3954 if (addToIndex)
3955 {
3956 Doxygen::indexList->decContentsDepth();
3957 }
3958 if (ftv)
3959 {
3960 ftv->decContentsDepth();
3961 }
3962 //gd->visited=TRUE;
3963 }
3964 }
3965
writeGroupHierarchy(OutputList & ol,FTVHelp * ftv,bool addToIndex)3966 static void writeGroupHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex)
3967 {
3968 if (ftv)
3969 {
3970 ol.pushGeneratorState();
3971 ol.disable(OutputGenerator::Html);
3972 }
3973 startIndexHierarchy(ol,0);
3974 for (const auto &gd : *Doxygen::groupLinkedMap)
3975 {
3976 writeGroupTreeNode(ol,gd.get(),0,ftv,addToIndex);
3977 }
3978 endIndexHierarchy(ol,0);
3979 if (ftv)
3980 {
3981 ol.popGeneratorState();
3982 }
3983 }
3984
3985 //----------------------------------------------------------------------------
3986
writeGroupIndex(OutputList & ol)3987 static void writeGroupIndex(OutputList &ol)
3988 {
3989 if (documentedGroups==0) return;
3990 ol.pushGeneratorState();
3991 // 1.{
3992 ol.disable(OutputGenerator::Man);
3993 ol.disable(OutputGenerator::Docbook);
3994 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Modules);
3995 QCString title = lne ? lne->title() : theTranslator->trModules();
3996 bool addToIndex = lne==0 || lne->visible();
3997
3998 startFile(ol,"modules",QCString(),title,HLI_Modules);
3999 startTitle(ol,QCString());
4000 ol.parseText(title);
4001 endTitle(ol,QCString(),QCString());
4002 ol.startContents();
4003 ol.startTextBlock();
4004 ol.parseText(lne ? lne->intro() : theTranslator->trModulesDescription());
4005 ol.endTextBlock();
4006
4007 // ---------------
4008 // Normal group index for Latex/RTF
4009 // ---------------
4010 // 2.{
4011 ol.pushGeneratorState();
4012 ol.disable(OutputGenerator::Html);
4013 Doxygen::indexList->disable();
4014
4015 writeGroupHierarchy(ol,0,FALSE);
4016
4017 Doxygen::indexList->enable();
4018 ol.popGeneratorState();
4019 // 2.}
4020
4021 // ---------------
4022 // interactive group index for HTML
4023 // ---------------
4024 // 2.{
4025 ol.pushGeneratorState();
4026 ol.disableAllBut(OutputGenerator::Html);
4027
4028 {
4029 if (addToIndex)
4030 {
4031 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"modules",QCString(),TRUE,TRUE);
4032 Doxygen::indexList->incContentsDepth();
4033 }
4034 FTVHelp* ftv = new FTVHelp(FALSE);
4035 writeGroupHierarchy(ol,ftv,addToIndex);
4036 TextStream t;
4037 ftv->generateTreeViewInline(t);
4038 ol.disableAllBut(OutputGenerator::Html);
4039 ol.writeString(t.str().c_str());
4040 delete ftv;
4041 if (addToIndex)
4042 {
4043 Doxygen::indexList->decContentsDepth();
4044 }
4045 }
4046 ol.popGeneratorState();
4047 // 2.}
4048
4049 endFile(ol);
4050 ol.popGeneratorState();
4051 // 1.}
4052 }
4053
4054 //----------------------------------------------------------------------------
4055
writeConceptList(const ConceptLinkedRefMap & concepts,FTVHelp * ftv,bool addToIndex)4056 static void writeConceptList(const ConceptLinkedRefMap &concepts, FTVHelp *ftv,bool addToIndex)
4057 {
4058 for (const auto &cd : concepts)
4059 {
4060 ftv->addContentsItem(false,cd->displayName(FALSE),cd->getReference(),
4061 cd->getOutputFileBase(),QCString(),false,cd->partOfGroups().empty(),cd);
4062 if (addToIndex)
4063 {
4064 Doxygen::indexList->addContentsItem(false,cd->displayName(FALSE),cd->getReference(),
4065 cd->getOutputFileBase(),QCString(),false,cd->partOfGroups().empty());
4066 }
4067 }
4068 }
4069
4070 static void writeConceptTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv,
4071 bool rootOnly, bool addToIndex);
4072
writeConceptTreeInsideNamespace(const NamespaceLinkedRefMap & nsLinkedMap,FTVHelp * ftv,bool rootOnly,bool addToIndex)4073 static void writeConceptTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv,
4074 bool rootOnly, bool addToIndex)
4075 {
4076 for (const auto &nd : nsLinkedMap)
4077 {
4078 writeConceptTreeInsideNamespaceElement(nd,ftv,rootOnly,addToIndex);
4079 }
4080 }
4081
4082
writeConceptTreeInsideNamespaceElement(const NamespaceDef * nd,FTVHelp * ftv,bool rootOnly,bool addToIndex)4083 static void writeConceptTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv,
4084 bool rootOnly, bool addToIndex)
4085 {
4086 if (!nd->isAnonymous() &&
4087 (!rootOnly || nd->getOuterScope()==Doxygen::globalScope))
4088 {
4089 bool isDir = namespaceHasNestedConcept(nd);
4090 bool isLinkable = nd->isLinkableInProject();
4091
4092 //printf("namespace %s isDir=%d\n",qPrint(nd->name()),isDir);
4093
4094 QCString ref;
4095 QCString file;
4096 if (isLinkable)
4097 {
4098 ref = nd->getReference();
4099 file = nd->getOutputFileBase();
4100 }
4101
4102 if (isDir)
4103 {
4104 ftv->addContentsItem(isDir,nd->localName(),ref,file,QCString(),FALSE,TRUE,nd);
4105
4106 if (addToIndex)
4107 {
4108 // the namespace entry is already shown under the namespace list so don't
4109 // add it to the nav index and don't create a separate index file for it otherwise
4110 // it will overwrite the one written for the namespace list.
4111 Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(),
4112 false, // separateIndex
4113 false // addToNavIndex
4114 );
4115 }
4116 if (addToIndex)
4117 {
4118 Doxygen::indexList->incContentsDepth();
4119 }
4120
4121 ftv->incContentsDepth();
4122 writeConceptTreeInsideNamespace(nd->getNamespaces(),ftv,FALSE,addToIndex);
4123 writeConceptList(nd->getConcepts(),ftv,addToIndex);
4124 ftv->decContentsDepth();
4125
4126 if (addToIndex)
4127 {
4128 Doxygen::indexList->decContentsDepth();
4129 }
4130 }
4131 }
4132 }
4133
writeConceptRootList(FTVHelp * ftv,bool addToIndex)4134 static void writeConceptRootList(FTVHelp *ftv,bool addToIndex)
4135 {
4136 for (const auto &cd : *Doxygen::conceptLinkedMap)
4137 {
4138 if (cd->getOuterScope()==0 ||
4139 cd->getOuterScope()==Doxygen::globalScope)
4140 {
4141 //printf("*** adding %s hasSubPages=%d hasSections=%d\n",qPrint(pageTitle),hasSubPages,hasSections);
4142 ftv->addContentsItem(
4143 false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
4144 QCString(),false,cd->partOfGroups().empty(),cd.get());
4145 if (addToIndex)
4146 {
4147 Doxygen::indexList->addContentsItem(
4148 false,cd->localName(),cd->getReference(),cd->getOutputFileBase(),
4149 QCString(),false,cd->partOfGroups().empty(),cd.get());
4150 }
4151 }
4152 }
4153 }
4154
writeConceptIndex(OutputList & ol)4155 static void writeConceptIndex(OutputList &ol)
4156 {
4157 if (documentedConcepts==0) return;
4158 ol.pushGeneratorState();
4159 // 1.{
4160 ol.disable(OutputGenerator::Man);
4161 ol.disable(OutputGenerator::Docbook);
4162 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Concepts);
4163 QCString title = lne ? lne->title() : theTranslator->trConceptList();
4164 bool addToIndex = lne==0 || lne->visible();
4165
4166 startFile(ol,"concepts",QCString(),title,HLI_Concepts);
4167 startTitle(ol,QCString());
4168 ol.parseText(title);
4169 endTitle(ol,QCString(),QCString());
4170 ol.startContents();
4171 ol.startTextBlock();
4172 ol.parseText(lne ? lne->intro() : theTranslator->trConceptListDescription(Config_getBool(EXTRACT_ALL)));
4173 ol.endTextBlock();
4174
4175 // ---------------
4176 // Normal group index for Latex/RTF
4177 // ---------------
4178 // 2.{
4179 ol.pushGeneratorState();
4180 ol.disable(OutputGenerator::Html);
4181
4182 bool first=TRUE;
4183 for (const auto &cd : *Doxygen::conceptLinkedMap)
4184 {
4185 if (cd->isLinkableInProject())
4186 {
4187 if (first)
4188 {
4189 ol.startIndexList();
4190 first=FALSE;
4191 }
4192 //ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name());
4193 ol.startIndexKey();
4194 ol.writeObjectLink(QCString(),cd->getOutputFileBase(),QCString(),cd->displayName());
4195 ol.endIndexKey();
4196
4197 bool hasBrief = !cd->briefDescription().isEmpty();
4198 ol.startIndexValue(hasBrief);
4199 if (hasBrief)
4200 {
4201 //ol.docify(" (");
4202 ol.generateDoc(
4203 cd->briefFile(),cd->briefLine(),
4204 cd.get(),0,
4205 cd->briefDescription(TRUE),
4206 FALSE, // index words
4207 FALSE, // isExample
4208 QCString(), // example name
4209 TRUE, // single line
4210 TRUE, // link from index
4211 Config_getBool(MARKDOWN_SUPPORT)
4212 );
4213 //ol.docify(")");
4214 }
4215 ol.endIndexValue(cd->getOutputFileBase(),hasBrief);
4216
4217 }
4218 }
4219 if (!first) ol.endIndexList();
4220
4221 ol.popGeneratorState();
4222 // 2.}
4223
4224 // ---------------
4225 // interactive group index for HTML
4226 // ---------------
4227 // 2.{
4228 ol.pushGeneratorState();
4229 ol.disableAllBut(OutputGenerator::Html);
4230
4231 {
4232 if (addToIndex)
4233 {
4234 Doxygen::indexList->addContentsItem(TRUE,title,QCString(),"concepts",QCString(),TRUE,TRUE);
4235 Doxygen::indexList->incContentsDepth();
4236 }
4237 FTVHelp ftv(false);
4238 for (const auto &nd : *Doxygen::namespaceLinkedMap)
4239 {
4240 writeConceptTreeInsideNamespaceElement(nd.get(),&ftv,true,addToIndex);
4241 }
4242 writeConceptRootList(&ftv,addToIndex);
4243 TextStream t;
4244 ftv.generateTreeViewInline(t);
4245 ol.writeString(t.str().c_str());
4246 if (addToIndex)
4247 {
4248 Doxygen::indexList->decContentsDepth();
4249 }
4250 }
4251 ol.popGeneratorState();
4252 // 2.}
4253
4254 endFile(ol);
4255 ol.popGeneratorState();
4256 // 1.}
4257 }
4258
4259 //----------------------------------------------------------------------------
4260
writeUserGroupStubPage(OutputList & ol,LayoutNavEntry * lne)4261 static void writeUserGroupStubPage(OutputList &ol,LayoutNavEntry *lne)
4262 {
4263 if (lne->baseFile().left(9)=="usergroup")
4264 {
4265 ol.pushGeneratorState();
4266 ol.disableAllBut(OutputGenerator::Html);
4267 startFile(ol,lne->baseFile(),QCString(),lne->title(),HLI_UserGroup);
4268 startTitle(ol,QCString());
4269 ol.parseText(lne->title());
4270 endTitle(ol,QCString(),QCString());
4271 ol.startContents();
4272 int count=0;
4273 for (const auto &entry: lne->children())
4274 {
4275 if (entry->visible()) count++;
4276 }
4277 if (count>0)
4278 {
4279 ol.writeString("<ul>\n");
4280 for (const auto &entry: lne->children())
4281 {
4282 if (entry->visible())
4283 {
4284 ol.writeString("<li><a href=\""+entry->url()+"\"><span>"+
4285 fixSpaces(entry->title())+"</span></a></li>\n");
4286 }
4287 }
4288 ol.writeString("</ul>\n");
4289 }
4290 endFile(ol);
4291 ol.popGeneratorState();
4292 }
4293 }
4294
4295 //----------------------------------------------------------------------------
4296
4297
writeIndex(OutputList & ol)4298 static void writeIndex(OutputList &ol)
4299 {
4300 static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
4301 static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
4302 static QCString projectName = Config_getString(PROJECT_NAME);
4303 // save old generator state
4304 ol.pushGeneratorState();
4305
4306 QCString projPrefix;
4307 if (!projectName.isEmpty())
4308 {
4309 projPrefix=projectName+" ";
4310 }
4311
4312 //--------------------------------------------------------------------
4313 // write HTML index
4314 //--------------------------------------------------------------------
4315 ol.disableAllBut(OutputGenerator::Html);
4316
4317 QCString defFileName =
4318 Doxygen::mainPage ? Doxygen::mainPage->docFile() : QCString("[generated]");
4319 int defLine =
4320 Doxygen::mainPage ? Doxygen::mainPage->docLine() : -1;
4321
4322 QCString title;
4323 if (!mainPageHasTitle())
4324 {
4325 title = theTranslator->trMainPage();
4326 }
4327 else if (Doxygen::mainPage)
4328 {
4329 title = filterTitle(Doxygen::mainPage->title().str());
4330 }
4331
4332 QCString indexName="index";
4333 ol.startFile(indexName,QCString(),title);
4334
4335 if (Doxygen::mainPage)
4336 {
4337 if (
4338 (!projectName.isEmpty() && mainPageHasTitle() && qstricmp(title,projectName)!=0)
4339 ) // to avoid duplicate entries in the treeview
4340 {
4341 Doxygen::indexList->addContentsItem(Doxygen::mainPage->hasSubPages(),title,QCString(),indexName,QCString(),Doxygen::mainPage->hasSubPages(),TRUE);
4342 }
4343 if (Doxygen::mainPage->hasSubPages() || Doxygen::mainPage->hasSections())
4344 {
4345 writePages(Doxygen::mainPage.get(),0);
4346 }
4347 }
4348
4349 ol.startQuickIndices();
4350 if (!Config_getBool(DISABLE_INDEX))
4351 {
4352 ol.writeQuickLinks(TRUE,HLI_Main,QCString());
4353 }
4354 ol.endQuickIndices();
4355 ol.writeSplitBar(indexName);
4356 ol.writeSearchInfo();
4357 bool headerWritten=FALSE;
4358 if (Doxygen::mainPage)
4359 {
4360 if (!Doxygen::mainPage->title().isEmpty())
4361 {
4362 if (Doxygen::mainPage->title().lower() != "notitle")
4363 ol.startPageDoc(Doxygen::mainPage->title());
4364 else
4365 ol.startPageDoc("");
4366 }
4367 else
4368 ol.startPageDoc(projectName);
4369 }
4370 if (Doxygen::mainPage && !Doxygen::mainPage->title().isEmpty())
4371 {
4372 if (Doxygen::mainPage->title().lower()!="notitle")
4373 {
4374 ol.startHeaderSection();
4375 ol.startTitleHead(QCString());
4376 ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->getStartBodyLine(),
4377 Doxygen::mainPage.get(),0,Doxygen::mainPage->title(),TRUE,FALSE,
4378 QCString(),TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
4379 headerWritten = TRUE;
4380 }
4381 }
4382 else
4383 {
4384 if (!projectName.isEmpty())
4385 {
4386 ol.startHeaderSection();
4387 ol.startTitleHead(QCString());
4388 ol.parseText(projPrefix+theTranslator->trDocumentation());
4389 headerWritten = TRUE;
4390 }
4391 }
4392 if (headerWritten)
4393 {
4394 ol.endTitleHead(QCString(),QCString());
4395 ol.endHeaderSection();
4396 }
4397
4398 ol.startContents();
4399 if (Config_getBool(DISABLE_INDEX) && Doxygen::mainPage==0)
4400 {
4401 ol.writeQuickLinks(FALSE,HLI_Main,QCString());
4402 }
4403
4404 if (Doxygen::mainPage)
4405 {
4406 Doxygen::insideMainPage=TRUE;
4407 if (Doxygen::mainPage->localToc().isHtmlEnabled() && Doxygen::mainPage->hasSections())
4408 {
4409 Doxygen::mainPage->writeToc(ol,Doxygen::mainPage->localToc());
4410 }
4411
4412 ol.startTextBlock();
4413 ol.generateDoc(defFileName,defLine,Doxygen::mainPage.get(),0,
4414 Doxygen::mainPage->documentation(),TRUE,FALSE,
4415 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
4416 ol.endTextBlock();
4417 ol.endPageDoc();
4418
4419 Doxygen::insideMainPage=FALSE;
4420 }
4421
4422 endFile(ol);
4423 ol.disable(OutputGenerator::Html);
4424
4425 //--------------------------------------------------------------------
4426 // write LaTeX/RTF index
4427 //--------------------------------------------------------------------
4428 ol.enable(OutputGenerator::Latex);
4429 ol.enable(OutputGenerator::Docbook);
4430 ol.enable(OutputGenerator::RTF);
4431
4432 ol.startFile("refman",QCString(),QCString());
4433 ol.startIndexSection(isTitlePageStart);
4434 ol.disable(OutputGenerator::Latex);
4435 ol.disable(OutputGenerator::Docbook);
4436
4437 if (projPrefix.isEmpty())
4438 {
4439 ol.parseText(theTranslator->trReferenceManual());
4440 }
4441 else
4442 {
4443 ol.parseText(projPrefix);
4444 }
4445
4446 if (!Config_getString(PROJECT_NUMBER).isEmpty())
4447 {
4448 ol.startProjectNumber();
4449 ol.generateDoc(defFileName,defLine,Doxygen::mainPage.get(),0,Config_getString(PROJECT_NUMBER),FALSE,FALSE,
4450 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
4451 ol.endProjectNumber();
4452 }
4453 ol.endIndexSection(isTitlePageStart);
4454 ol.startIndexSection(isTitlePageAuthor);
4455 ol.parseText(theTranslator->trGeneratedBy());
4456 ol.endIndexSection(isTitlePageAuthor);
4457 ol.enable(OutputGenerator::Latex);
4458 ol.enable(OutputGenerator::Docbook);
4459
4460 ol.lastIndexPage();
4461 if (Doxygen::mainPage)
4462 {
4463 ol.startIndexSection(isMainPage);
4464 if (mainPageHasTitle())
4465 {
4466 ol.parseText(Doxygen::mainPage->title());
4467 }
4468 else
4469 {
4470 ol.parseText(/*projPrefix+*/theTranslator->trMainPage());
4471 }
4472 ol.endIndexSection(isMainPage);
4473 }
4474 if (documentedPages>0)
4475 {
4476 //ol.parseText(projPrefix+theTranslator->trPageDocumentation());
4477 //ol.endIndexSection(isPageDocumentation);
4478 bool first=Doxygen::mainPage==0;
4479 for (const auto &pd : *Doxygen::pageLinkedMap)
4480 {
4481 if (!pd->getGroupDef() && !pd->isReference() &&
4482 (!pd->hasParentPage() || // not inside other page
4483 (Doxygen::mainPage.get()==pd->getOuterScope())) // or inside main page
4484 )
4485 {
4486 bool isCitationPage = pd->name()=="citelist";
4487 if (isCitationPage)
4488 {
4489 // For LaTeX the bibliograph is already written by \bibliography
4490 ol.pushGeneratorState();
4491 ol.disable(OutputGenerator::Latex);
4492 }
4493 title = pd->title();
4494 if (title.isEmpty()) title=pd->name();
4495
4496 ol.disable(OutputGenerator::Docbook);
4497 ol.startIndexSection(isPageDocumentation);
4498 ol.parseText(title);
4499 ol.endIndexSection(isPageDocumentation);
4500 ol.enable(OutputGenerator::Docbook);
4501
4502 ol.pushGeneratorState(); // write TOC title (RTF only)
4503 ol.disableAllBut(OutputGenerator::RTF);
4504 ol.startIndexSection(isPageDocumentation2);
4505 ol.parseText(title);
4506 ol.endIndexSection(isPageDocumentation2);
4507 ol.popGeneratorState();
4508
4509 ol.writeAnchor(QCString(),pd->getOutputFileBase());
4510
4511 ol.writePageLink(pd->getOutputFileBase(),first);
4512 first=FALSE;
4513
4514 if (isCitationPage)
4515 {
4516 ol.popGeneratorState();
4517 }
4518 }
4519 }
4520 }
4521
4522 ol.disable(OutputGenerator::Docbook);
4523 if (!Config_getBool(LATEX_HIDE_INDICES))
4524 {
4525 //if (indexedPages>0)
4526 //{
4527 // ol.startIndexSection(isPageIndex);
4528 // ol.parseText(/*projPrefix+*/ theTranslator->trPageIndex());
4529 // ol.endIndexSection(isPageIndex);
4530 //}
4531 if (documentedGroups>0)
4532 {
4533 ol.startIndexSection(isModuleIndex);
4534 ol.parseText(/*projPrefix+*/ theTranslator->trModuleIndex());
4535 ol.endIndexSection(isModuleIndex);
4536 }
4537 if (Config_getBool(SHOW_NAMESPACES) && (documentedNamespaces>0))
4538 {
4539 ol.startIndexSection(isNamespaceIndex);
4540 ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModulesIndex():theTranslator->trNamespaceIndex()));
4541 ol.endIndexSection(isNamespaceIndex);
4542 }
4543 if (documentedConcepts>0)
4544 {
4545 ol.startIndexSection(isConceptIndex);
4546 ol.parseText(/*projPrefix+*/theTranslator->trConceptIndex());
4547 ol.endIndexSection(isConceptIndex);
4548 }
4549 if (hierarchyInterfaces>0)
4550 {
4551 ol.startIndexSection(isClassHierarchyIndex);
4552 ol.parseText(/*projPrefix+*/theTranslator->trHierarchicalIndex());
4553 ol.endIndexSection(isClassHierarchyIndex);
4554 }
4555 if (hierarchyClasses>0)
4556 {
4557 ol.startIndexSection(isClassHierarchyIndex);
4558 ol.parseText(/*projPrefix+*/
4559 (fortranOpt ? theTranslator->trCompoundIndexFortran() :
4560 vhdlOpt ? theTranslator->trHierarchicalIndex() :
4561 theTranslator->trHierarchicalIndex()
4562 ));
4563 ol.endIndexSection(isClassHierarchyIndex);
4564 }
4565 if (hierarchyExceptions>0)
4566 {
4567 ol.startIndexSection(isClassHierarchyIndex);
4568 ol.parseText(/*projPrefix+*/theTranslator->trHierarchicalIndex());
4569 ol.endIndexSection(isClassHierarchyIndex);
4570 }
4571 if (annotatedInterfacesPrinted>0)
4572 {
4573 ol.startIndexSection(isCompoundIndex);
4574 ol.parseText(/*projPrefix+*/theTranslator->trInterfaceIndex());
4575 ol.endIndexSection(isCompoundIndex);
4576 }
4577 if (annotatedClassesPrinted>0)
4578 {
4579 ol.startIndexSection(isCompoundIndex);
4580 ol.parseText(/*projPrefix+*/
4581 (fortranOpt ? theTranslator->trCompoundIndexFortran() :
4582 vhdlOpt ? theTranslator->trDesignUnitIndex() :
4583 theTranslator->trCompoundIndex()
4584 ));
4585 ol.endIndexSection(isCompoundIndex);
4586 }
4587 if (annotatedStructsPrinted>0)
4588 {
4589 ol.startIndexSection(isCompoundIndex);
4590 ol.parseText(/*projPrefix+*/theTranslator->trStructIndex());
4591 ol.endIndexSection(isCompoundIndex);
4592 }
4593 if (annotatedExceptionsPrinted>0)
4594 {
4595 ol.startIndexSection(isCompoundIndex);
4596 ol.parseText(/*projPrefix+*/theTranslator->trExceptionIndex());
4597 ol.endIndexSection(isCompoundIndex);
4598 }
4599 if (documentedFiles>0)
4600 {
4601 ol.startIndexSection(isFileIndex);
4602 ol.parseText(/*projPrefix+*/theTranslator->trFileIndex());
4603 ol.endIndexSection(isFileIndex);
4604 }
4605 }
4606 ol.enable(OutputGenerator::Docbook);
4607
4608 if (documentedGroups>0)
4609 {
4610 ol.startIndexSection(isModuleDocumentation);
4611 ol.parseText(/*projPrefix+*/theTranslator->trModuleDocumentation());
4612 ol.endIndexSection(isModuleDocumentation);
4613 }
4614 if (documentedNamespaces>0)
4615 {
4616 ol.startIndexSection(isNamespaceDocumentation);
4617 ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trModuleDocumentation():theTranslator->trNamespaceDocumentation()));
4618 ol.endIndexSection(isNamespaceDocumentation);
4619 }
4620 if (documentedConcepts>0)
4621 {
4622 ol.startIndexSection(isConceptDocumentation);
4623 ol.parseText(/*projPrefix+*/theTranslator->trConceptDocumentation());
4624 ol.endIndexSection(isConceptDocumentation);
4625 }
4626 if (annotatedInterfacesPrinted>0)
4627 {
4628 ol.startIndexSection(isClassDocumentation);
4629 ol.parseText(/*projPrefix+*/theTranslator->trInterfaceDocumentation());
4630 ol.endIndexSection(isClassDocumentation);
4631 }
4632 if (annotatedClassesPrinted>0)
4633 {
4634 ol.startIndexSection(isClassDocumentation);
4635 ol.parseText(/*projPrefix+*/(fortranOpt?theTranslator->trTypeDocumentation():theTranslator->trClassDocumentation()));
4636 ol.endIndexSection(isClassDocumentation);
4637 }
4638 if (annotatedStructsPrinted>0)
4639 {
4640 ol.startIndexSection(isClassDocumentation);
4641 ol.parseText(/*projPrefix+*/theTranslator->trStructDocumentation());
4642 ol.endIndexSection(isClassDocumentation);
4643 }
4644 if (annotatedExceptionsPrinted>0)
4645 {
4646 ol.startIndexSection(isClassDocumentation);
4647 ol.parseText(/*projPrefix+*/theTranslator->trExceptionDocumentation());
4648 ol.endIndexSection(isClassDocumentation);
4649 }
4650 if (documentedFiles>0)
4651 {
4652 ol.startIndexSection(isFileDocumentation);
4653 ol.parseText(/*projPrefix+*/theTranslator->trFileDocumentation());
4654 ol.endIndexSection(isFileDocumentation);
4655 }
4656 if (!Doxygen::exampleLinkedMap->empty())
4657 {
4658 ol.startIndexSection(isExampleDocumentation);
4659 ol.parseText(/*projPrefix+*/theTranslator->trExampleDocumentation());
4660 ol.endIndexSection(isExampleDocumentation);
4661 }
4662 ol.endIndexSection(isEndIndex);
4663 endFile(ol);
4664
4665 if (Doxygen::mainPage)
4666 {
4667 Doxygen::insideMainPage=TRUE;
4668 ol.disable(OutputGenerator::Man);
4669 startFile(ol,Doxygen::mainPage->name(),QCString(),Doxygen::mainPage->title());
4670 ol.startContents();
4671 ol.startTextBlock();
4672 ol.generateDoc(defFileName,defLine,Doxygen::mainPage.get(),0,
4673 Doxygen::mainPage->documentation(),FALSE,FALSE,
4674 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)
4675 );
4676 ol.endTextBlock();
4677 endFile(ol);
4678 ol.enable(OutputGenerator::Man);
4679 Doxygen::insideMainPage=FALSE;
4680 }
4681
4682 ol.popGeneratorState();
4683 }
4684
4685 static std::vector<bool> indexWritten;
4686
writeIndexHierarchyEntries(OutputList & ol,const LayoutNavEntryList & entries)4687 static void writeIndexHierarchyEntries(OutputList &ol,const LayoutNavEntryList &entries)
4688 {
4689 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
4690 for (const auto &lne : entries)
4691 {
4692 LayoutNavEntry::Kind kind = lne->kind();
4693 uint index = (uint)kind;
4694 if (index>=indexWritten.size())
4695 {
4696 size_t i;
4697 size_t oldSize = indexWritten.size();
4698 size_t newSize = index+1;
4699 indexWritten.resize(newSize);
4700 for (i=oldSize;i<newSize;i++) indexWritten.at(i)=FALSE;
4701 }
4702 //printf("starting %s kind=%d\n",qPrint(lne->title()),lne->kind());
4703 bool addToIndex=lne->visible();
4704 bool needsClosing=FALSE;
4705 if (!indexWritten.at(index))
4706 {
4707 switch(kind)
4708 {
4709 case LayoutNavEntry::MainPage:
4710 msg("Generating index page...\n");
4711 writeIndex(ol);
4712 break;
4713 case LayoutNavEntry::Pages:
4714 msg("Generating page index...\n");
4715 writePageIndex(ol);
4716 break;
4717 case LayoutNavEntry::Modules:
4718 msg("Generating module index...\n");
4719 writeGroupIndex(ol);
4720 break;
4721 case LayoutNavEntry::Namespaces:
4722 {
4723 static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
4724 if (showNamespaces)
4725 {
4726 if (documentedNamespaces>0 && addToIndex)
4727 {
4728 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4729 Doxygen::indexList->incContentsDepth();
4730 needsClosing=TRUE;
4731 }
4732 if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Namespaces)!=lne.get()) // for backward compatibility with old layout file
4733 {
4734 msg("Generating namespace index...\n");
4735 writeNamespaceIndex(ol);
4736 }
4737 }
4738 }
4739 break;
4740 case LayoutNavEntry::NamespaceList:
4741 {
4742 static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
4743 if (showNamespaces)
4744 {
4745 msg("Generating namespace index...\n");
4746 writeNamespaceIndex(ol);
4747 }
4748 }
4749 break;
4750 case LayoutNavEntry::NamespaceMembers:
4751 msg("Generating namespace member index...\n");
4752 writeNamespaceMemberIndex(ol);
4753 break;
4754 case LayoutNavEntry::Classes:
4755 if (annotatedClasses>0 && addToIndex)
4756 {
4757 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4758 Doxygen::indexList->incContentsDepth();
4759 needsClosing=TRUE;
4760 }
4761 if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Classes)!=lne.get()) // for backward compatibility with old layout file
4762 {
4763 msg("Generating annotated compound index...\n");
4764 writeAnnotatedIndex(ol);
4765 }
4766 break;
4767 case LayoutNavEntry::Concepts:
4768 msg("Generating concept index...\n");
4769 writeConceptIndex(ol);
4770 break;
4771 case LayoutNavEntry::ClassList:
4772 msg("Generating annotated compound index...\n");
4773 writeAnnotatedIndex(ol);
4774 break;
4775 case LayoutNavEntry::ClassIndex:
4776 msg("Generating alphabetical compound index...\n");
4777 writeAlphabeticalIndex(ol);
4778 break;
4779 case LayoutNavEntry::ClassHierarchy:
4780 msg("Generating hierarchical class index...\n");
4781 writeHierarchicalIndex(ol);
4782 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
4783 {
4784 msg("Generating graphical class hierarchy...\n");
4785 writeGraphicalClassHierarchy(ol);
4786 }
4787 break;
4788 case LayoutNavEntry::ClassMembers:
4789 if (!sliceOpt)
4790 {
4791 msg("Generating member index...\n");
4792 writeClassMemberIndex(ol);
4793 }
4794 break;
4795 case LayoutNavEntry::Interfaces:
4796 if (sliceOpt && annotatedInterfaces>0 && addToIndex)
4797 {
4798 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4799 Doxygen::indexList->incContentsDepth();
4800 needsClosing=TRUE;
4801 }
4802 break;
4803 case LayoutNavEntry::InterfaceList:
4804 if (sliceOpt)
4805 {
4806 msg("Generating annotated interface index...\n");
4807 writeAnnotatedInterfaceIndex(ol);
4808 }
4809 break;
4810 case LayoutNavEntry::InterfaceIndex:
4811 if (sliceOpt)
4812 {
4813 msg("Generating alphabetical interface index...\n");
4814 writeAlphabeticalInterfaceIndex(ol);
4815 }
4816 break;
4817 case LayoutNavEntry::InterfaceHierarchy:
4818 if (sliceOpt)
4819 {
4820 msg("Generating hierarchical interface index...\n");
4821 writeHierarchicalInterfaceIndex(ol);
4822 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
4823 {
4824 msg("Generating graphical interface hierarchy...\n");
4825 writeGraphicalInterfaceHierarchy(ol);
4826 }
4827 }
4828 break;
4829 case LayoutNavEntry::Structs:
4830 if (sliceOpt && annotatedStructs>0 && addToIndex)
4831 {
4832 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4833 Doxygen::indexList->incContentsDepth();
4834 needsClosing=TRUE;
4835 }
4836 break;
4837 case LayoutNavEntry::StructList:
4838 if (sliceOpt)
4839 {
4840 msg("Generating annotated struct index...\n");
4841 writeAnnotatedStructIndex(ol);
4842 }
4843 break;
4844 case LayoutNavEntry::StructIndex:
4845 if (sliceOpt)
4846 {
4847 msg("Generating alphabetical struct index...\n");
4848 writeAlphabeticalStructIndex(ol);
4849 }
4850 break;
4851 case LayoutNavEntry::Exceptions:
4852 if (sliceOpt && annotatedExceptions>0 && addToIndex)
4853 {
4854 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4855 Doxygen::indexList->incContentsDepth();
4856 needsClosing=TRUE;
4857 }
4858 break;
4859 case LayoutNavEntry::ExceptionList:
4860 if (sliceOpt)
4861 {
4862 msg("Generating annotated exception index...\n");
4863 writeAnnotatedExceptionIndex(ol);
4864 }
4865 break;
4866 case LayoutNavEntry::ExceptionIndex:
4867 if (sliceOpt)
4868 {
4869 msg("Generating alphabetical exception index...\n");
4870 writeAlphabeticalExceptionIndex(ol);
4871 }
4872 break;
4873 case LayoutNavEntry::ExceptionHierarchy:
4874 if (sliceOpt)
4875 {
4876 msg("Generating hierarchical exception index...\n");
4877 writeHierarchicalExceptionIndex(ol);
4878 if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY))
4879 {
4880 msg("Generating graphical exception hierarchy...\n");
4881 writeGraphicalExceptionHierarchy(ol);
4882 }
4883 }
4884 break;
4885 case LayoutNavEntry::Files:
4886 {
4887 if (documentedFiles>0 && addToIndex)
4888 {
4889 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString());
4890 Doxygen::indexList->incContentsDepth();
4891 needsClosing=TRUE;
4892 }
4893 if (LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Files)!=lne.get()) // for backward compatibility with old layout file
4894 {
4895 msg("Generating file index...\n");
4896 writeFileIndex(ol);
4897 }
4898 }
4899 break;
4900 case LayoutNavEntry::FileList:
4901 msg("Generating file index...\n");
4902 writeFileIndex(ol);
4903 break;
4904 case LayoutNavEntry::FileGlobals:
4905 msg("Generating file member index...\n");
4906 writeFileMemberIndex(ol);
4907 break;
4908 case LayoutNavEntry::Examples:
4909 msg("Generating example index...\n");
4910 writeExampleIndex(ol);
4911 break;
4912 case LayoutNavEntry::User:
4913 {
4914 // prepend a ! or ^ marker to the URL to avoid tampering with it
4915 QCString url = correctURL(lne->url(),"!"); // add ! to relative URL
4916 bool isRelative=url.at(0)=='!';
4917 if (!url.isEmpty() && !isRelative) // absolute URL
4918 {
4919 url.prepend("^"); // prepend ^ to absolute URL
4920 }
4921 bool isRef = lne->baseFile().left(4)=="@ref" || lne->baseFile().left(4)=="\\ref";
4922 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),url,QCString(),FALSE,isRef || isRelative);
4923 }
4924 break;
4925 case LayoutNavEntry::UserGroup:
4926 if (addToIndex)
4927 {
4928 QCString url = correctURL(lne->url(),"!"); // add ! to relative URL
4929 if (!url.isEmpty())
4930 {
4931 if (url=="!") // result of a "[none]" url
4932 {
4933 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),QCString(),QCString(),FALSE,FALSE);
4934 }
4935 else
4936 {
4937 bool isRelative=url.at(0)=='!';
4938 if (!isRelative) // absolute URL
4939 {
4940 url.prepend("^"); // prepend ^ to absolute URL
4941 }
4942 bool isRef = lne->baseFile().left(4)=="@ref" || lne->baseFile().left(4)=="\\ref";
4943 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),url,QCString(),FALSE,isRef || isRelative);
4944 }
4945 }
4946 else
4947 {
4948 Doxygen::indexList->addContentsItem(TRUE,lne->title(),QCString(),lne->baseFile(),QCString(),TRUE,TRUE);
4949 }
4950 Doxygen::indexList->incContentsDepth();
4951 needsClosing=TRUE;
4952 }
4953 writeUserGroupStubPage(ol,lne.get());
4954 break;
4955 case LayoutNavEntry::None:
4956 assert(kind != LayoutNavEntry::None); // should never happen, means not properly initialized
4957 break;
4958 }
4959 if (kind!=LayoutNavEntry::User && kind!=LayoutNavEntry::UserGroup) // User entry may appear multiple times
4960 {
4961 indexWritten.at(index)=TRUE;
4962 }
4963 }
4964 writeIndexHierarchyEntries(ol,lne->children());
4965 if (needsClosing)
4966 {
4967 switch(kind)
4968 {
4969 case LayoutNavEntry::Namespaces:
4970 case LayoutNavEntry::Classes:
4971 case LayoutNavEntry::Files:
4972 case LayoutNavEntry::UserGroup:
4973 Doxygen::indexList->decContentsDepth();
4974 break;
4975 default:
4976 break;
4977 }
4978 }
4979 //printf("ending %s kind=%d\n",qPrint(lne->title()),lne->kind());
4980 }
4981 }
4982
quickLinkVisible(LayoutNavEntry::Kind kind)4983 static bool quickLinkVisible(LayoutNavEntry::Kind kind)
4984 {
4985 static bool showNamespaces = Config_getBool(SHOW_NAMESPACES);
4986 static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
4987 switch (kind)
4988 {
4989 case LayoutNavEntry::MainPage: return TRUE;
4990 case LayoutNavEntry::User: return TRUE;
4991 case LayoutNavEntry::UserGroup: return TRUE;
4992 case LayoutNavEntry::Pages: return indexedPages>0;
4993 case LayoutNavEntry::Modules: return documentedGroups>0;
4994 case LayoutNavEntry::Namespaces: return documentedNamespaces>0 && showNamespaces;
4995 case LayoutNavEntry::NamespaceList: return documentedNamespaces>0 && showNamespaces;
4996 case LayoutNavEntry::NamespaceMembers: return documentedNamespaceMembers[NMHL_All]>0;
4997 case LayoutNavEntry::Concepts: return documentedConcepts>0;
4998 case LayoutNavEntry::Classes: return annotatedClasses>0;
4999 case LayoutNavEntry::ClassList: return annotatedClasses>0;
5000 case LayoutNavEntry::ClassIndex: return annotatedClasses>0;
5001 case LayoutNavEntry::ClassHierarchy: return hierarchyClasses>0;
5002 case LayoutNavEntry::ClassMembers: return documentedClassMembers[CMHL_All]>0 && !sliceOpt;
5003 case LayoutNavEntry::Interfaces: return annotatedInterfaces>0;
5004 case LayoutNavEntry::InterfaceList: return annotatedInterfaces>0;
5005 case LayoutNavEntry::InterfaceIndex: return annotatedInterfaces>0;
5006 case LayoutNavEntry::InterfaceHierarchy: return hierarchyInterfaces>0;
5007 case LayoutNavEntry::Structs: return annotatedStructs>0;
5008 case LayoutNavEntry::StructList: return annotatedStructs>0;
5009 case LayoutNavEntry::StructIndex: return annotatedStructs>0;
5010 case LayoutNavEntry::Exceptions: return annotatedExceptions>0;
5011 case LayoutNavEntry::ExceptionList: return annotatedExceptions>0;
5012 case LayoutNavEntry::ExceptionIndex: return annotatedExceptions>0;
5013 case LayoutNavEntry::ExceptionHierarchy: return hierarchyExceptions>0;
5014 case LayoutNavEntry::Files: return documentedFiles>0;
5015 case LayoutNavEntry::FileList: return documentedFiles>0;
5016 case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0;
5017 case LayoutNavEntry::Examples: return !Doxygen::exampleLinkedMap->empty();
5018 case LayoutNavEntry::None: // should never happen, means not properly initialized
5019 assert(kind != LayoutNavEntry::None);
5020 return FALSE;
5021 }
5022 return FALSE;
5023 }
5024
5025 template<class T,std::size_t total>
renderMemberIndicesAsJs(std::ostream & t,const int * numDocumented,const std::array<MemberIndexMap,total> & memberLists,const T * (* getInfo)(size_t hl))5026 void renderMemberIndicesAsJs(std::ostream &t,
5027 const int *numDocumented,
5028 const std::array<MemberIndexMap,total> &memberLists,
5029 const T *(*getInfo)(size_t hl))
5030 {
5031 // index items per category member lists
5032 bool firstMember=TRUE;
5033 for (std::size_t i=0;i<total;i++)
5034 {
5035 if (numDocumented[i]>0)
5036 {
5037 t << ",";
5038 if (firstMember)
5039 {
5040 t << "children:[";
5041 firstMember=FALSE;
5042 }
5043 t << "\n{text:\"" << convertToJSString(getInfo(i)->title) << "\",url:\""
5044 << convertToJSString(getInfo(i)->fname+Doxygen::htmlFileExtension) << "\"";
5045
5046 // Check if we have many members, then add sub entries per letter...
5047 // quick alphabetical index
5048 bool quickIndex = numDocumented[i]>maxItemsBeforeQuickIndex;
5049 if (quickIndex)
5050 {
5051 bool multiPageIndex=FALSE;
5052 if (numDocumented[i]>MAX_ITEMS_BEFORE_MULTIPAGE_INDEX)
5053 {
5054 multiPageIndex=TRUE;
5055 }
5056 t << ",children:[\n";
5057 bool firstLetter=TRUE;
5058 for (const auto &kv : memberLists[i])
5059 {
5060 if (!firstLetter) t << ",\n";
5061 std::string letter = kv.first;
5062 QCString ci(letter);
5063 QCString is(letterToLabel(ci));
5064 QCString anchor;
5065 QCString extension=Doxygen::htmlFileExtension;
5066 QCString fullName = getInfo(i)->fname;
5067 if (!multiPageIndex || firstLetter)
5068 anchor=fullName+extension+"#index_";
5069 else // other pages of multi page index
5070 anchor=fullName+"_"+is+extension+"#index_";
5071 t << "{text:\"" << convertToJSString(ci) << "\",url:\""
5072 << convertToJSString(anchor+convertToId(is)) << "\"}";
5073 firstLetter=FALSE;
5074 }
5075 t << "]";
5076 }
5077 t << "}";
5078 }
5079 }
5080 if (!firstMember)
5081 {
5082 t << "]";
5083 }
5084 }
5085
renderQuickLinksAsJs(std::ostream & t,LayoutNavEntry * root,bool first)5086 static bool renderQuickLinksAsJs(std::ostream &t,LayoutNavEntry *root,bool first)
5087 {
5088 int count=0;
5089 for (const auto &entry : root->children())
5090 {
5091 if (entry->visible() && quickLinkVisible(entry->kind())) count++;
5092 }
5093 if (count>0) // at least one item is visible
5094 {
5095 bool firstChild = TRUE;
5096 if (!first) t << ",";
5097 t << "children:[\n";
5098 for (const auto &entry : root->children())
5099 {
5100 if (entry->visible() && quickLinkVisible(entry->kind()))
5101 {
5102 if (!firstChild) t << ",\n";
5103 firstChild=FALSE;
5104 QCString url = entry->url();
5105 t << "{text:\"" << convertToJSString(entry->title()) << "\",url:\""
5106 << convertToJSString(url) << "\"";
5107 bool hasChildren=FALSE;
5108 if (entry->kind()==LayoutNavEntry::NamespaceMembers)
5109 {
5110 renderMemberIndicesAsJs(t,documentedNamespaceMembers,
5111 g_namespaceIndexLetterUsed,getNmhlInfo);
5112 }
5113 else if (entry->kind()==LayoutNavEntry::ClassMembers)
5114 {
5115 renderMemberIndicesAsJs(t,documentedClassMembers,
5116 g_classIndexLetterUsed,getCmhlInfo);
5117 }
5118 else if (entry->kind()==LayoutNavEntry::FileGlobals)
5119 {
5120 renderMemberIndicesAsJs(t,documentedFileMembers,
5121 g_fileIndexLetterUsed,getFmhlInfo);
5122 }
5123 else // recursive into child list
5124 {
5125 hasChildren = renderQuickLinksAsJs(t,entry.get(),FALSE);
5126 }
5127 if (hasChildren) t << "]";
5128 t << "}";
5129 }
5130 }
5131 }
5132 return count>0;
5133 }
5134
writeMenuData()5135 static void writeMenuData()
5136 {
5137 if (!Config_getBool(GENERATE_HTML) || Config_getBool(DISABLE_INDEX)) return;
5138 QCString outputDir = Config_getBool(HTML_OUTPUT);
5139 LayoutNavEntry *root = LayoutDocManager::instance().rootNavEntry();
5140 std::ofstream t(outputDir.str()+"/menudata.js",std::ofstream::out | std::ofstream::binary);
5141 if (t.is_open())
5142 {
5143 t << JAVASCRIPT_LICENSE_TEXT;
5144 t << "var menudata={";
5145 bool hasChildren = renderQuickLinksAsJs(t,root,TRUE);
5146 if (hasChildren) t << "]";
5147 t << "}\n";
5148 }
5149 }
5150
writeIndexHierarchy(OutputList & ol)5151 void writeIndexHierarchy(OutputList &ol)
5152 {
5153 writeMenuData();
5154 LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry();
5155 if (lne)
5156 {
5157 writeIndexHierarchyEntries(ol,lne->children());
5158 }
5159 }
5160