My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dirdef.cpp
Go to the documentation of this file.
1 #include "md5.h"
2 
3 #include "dirdef.h"
4 #include "filename.h"
5 #include "doxygen.h"
6 #include "util.h"
7 #include "outputlist.h"
8 #include "language.h"
9 #include "message.h"
10 #include "dot.h"
11 #include "layout.h"
12 #include "ftextstream.h"
13 #include "config.h"
14 #include "docparser.h"
15 
16 //----------------------------------------------------------------------
17 // method implementation
18 
19 static int g_dirCount=0;
20 
21 DirDef::DirDef(const char *path) : Definition(path,1,1,path), visited(FALSE)
22 {
23  bool fullPathNames = Config_getBool(FULL_PATH_NAMES);
24  // get display name (stipping the paths mentioned in STRIP_FROM_PATH)
25  // get short name (last part of path)
26  m_shortName = path;
27  m_diskName = path;
28  if (m_shortName.at(m_shortName.length()-1)=='/')
29  { // strip trailing /
30  m_shortName = m_shortName.left(m_shortName.length()-1);
31  }
32  int pi=m_shortName.findRev('/');
33  if (pi!=-1)
34  { // remove everything till the last /
35  m_shortName = m_shortName.mid(pi+1);
36  }
38  m_dispName = fullPathNames ? stripFromPath(path) : m_shortName;
39  if (m_dispName.length()>0 && m_dispName.at(m_dispName.length()-1)=='/')
40  { // strip trailing /
41  m_dispName = m_dispName.left(m_dispName.length()-1);
42  }
43 
44  m_fileList = new FileList;
45  m_usedDirs = new QDict<UsedDir>(257);
46  m_usedDirs->setAutoDelete(TRUE);
48  m_level=-1;
49  m_parent=0;
50 }
51 
53 {
54  delete m_fileList;
55  delete m_usedDirs;
56 }
57 
59 {
60  return !isReference();
61 }
62 
63 bool DirDef::isLinkable() const
64 {
65  return isReference() || isLinkableInProject();
66 }
67 
69 {
70  m_subdirs.append(subdir);
71  subdir->setOuterScope(this);
72  subdir->m_parent=this;
73 }
74 
76 {
77  m_fileList->append(fd);
78  fd->setDirDef(this);
79 }
80 
82 {
83  m_subdirs.sort();
84  m_fileList->sort();
85 }
86 
87 static QCString encodeDirName(const QCString &anchor)
88 {
89  // convert to md5 hash
90  uchar md5_sig[16];
91  QCString sigStr(33);
92  MD5Buffer((const unsigned char *)anchor.data(),anchor.length(),md5_sig);
93  MD5SigToString(md5_sig,sigStr.rawData(),33);
94  return sigStr;
95 
96  // old algorithm
97 // QCString result;
98 
99 // int l = anchor.length(),i;
100 // for (i=0;i<l;i++)
101 // {
102 // char c = anchor.at(i);
103 // if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'))
104 // {
105 // result+=c;
106 // }
107 // else
108 // {
109 // static char hexStr[]="0123456789ABCDEF";
110 // char escChar[]={ '_', 0, 0, 0 };
111 // escChar[1]=hexStr[c>>4];
112 // escChar[2]=hexStr[c&0xf];
113 // result+=escChar;
114 // }
115 // }
116 // return result;
117 }
118 
120 {
121  //printf("DirDef::getOutputFileBase() %s->dir_%s\n",
122  // m_diskName.data(),encodeDirName(m_diskName).data());
123  return "dir_"+encodeDirName(m_diskName);
124 }
125 
126 void DirDef::writeDetailedDescription(OutputList &ol,const QCString &title)
127 {
128  if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) ||
129  !documentation().isEmpty())
130  {
131  ol.pushGeneratorState();
133  ol.writeRuler();
134  ol.popGeneratorState();
135  ol.pushGeneratorState();
137  ol.writeAnchor(0,"details");
138  ol.popGeneratorState();
139  ol.startGroupHeader();
140  ol.parseText(title);
141  ol.endGroupHeader();
142 
143  // repeat brief description
144  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
145  {
146  ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
147  }
148  // separator between brief and details
149  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
150  !documentation().isEmpty())
151  {
152  ol.pushGeneratorState();
155  // ol.newParagraph(); // FIXME:PARA
156  ol.enableAll();
159  ol.writeString("\n\n");
160  ol.popGeneratorState();
161  }
162 
163  // write documentation
164  if (!documentation().isEmpty())
165  {
166  ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
167  }
168  }
169 }
170 
172 {
173  if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
174  {
175  DocRoot *rootNode = validatingParseDoc(
176  briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE);
177  if (rootNode && !rootNode->isEmpty())
178  {
179  ol.startParagraph();
180  ol.writeDoc(rootNode,this,0);
181  ol.pushGeneratorState();
183  ol.writeString(" \n");
185 
186  if (Config_getBool(REPEAT_BRIEF) ||
187  !documentation().isEmpty()
188  )
189  {
191  ol.startTextLink(0,"details");
193  ol.endTextLink();
194  }
195  ol.popGeneratorState();
196 
197  ol.endParagraph();
198  }
199  delete rootNode;
200  }
201  ol.writeSynopsis();
202 }
203 
205 {
206  // write graph dependency graph
207  if (Config_getBool(DIRECTORY_GRAPH) && Config_getBool(HAVE_DOT))
208  {
209  DotDirDeps dirDep(this);
210  if (!dirDep.isTrivial())
211  {
212  msg("Generating dependency graph for directory %s\n",displayName().data());
214  //ol.startParagraph();
215  ol.startDirDepGraph();
217  ol.endDirDepGraph(dirDep);
218  //ol.endParagraph();
219  ol.enableAll();
220  }
221  }
222 }
223 
225 {
226  int numSubdirs = 0;
227  QListIterator<DirDef> it(m_subdirs);
228  DirDef *dd;
229  for (it.toFirst();(dd=it.current());++it)
230  {
231  if (dd->hasDocumentation() || dd->getFiles()->count()>0)
232  {
233  numSubdirs++;
234  }
235  }
236 
237  // write subdir list
238  if (numSubdirs>0)
239  {
240  ol.startMemberHeader("subdirs");
241  ol.parseText(theTranslator->trDir(TRUE,FALSE));
242  ol.endMemberHeader();
243  ol.startMemberList();
244  for (it.toFirst();(dd=it.current());++it)
245  {
246  if (dd->hasDocumentation() || dd->getFiles()->count()==0)
247  {
250  ol.parseText(theTranslator->trDir(FALSE,TRUE)+" ");
251  ol.insertMemberAlign();
253  ol.endMemberItem();
254  if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
255  {
258  FALSE, // indexWords
259  FALSE, // isExample
260  0, // exampleName
261  TRUE, // single line
262  TRUE // link from index
263  );
265  }
266  ol.endMemberDeclaration(0,0);
267  }
268  }
269 
270  ol.endMemberList();
271  }
272 }
273 
275 {
276  int numFiles = 0;
277  QListIterator<FileDef> it(*m_fileList);
278  FileDef *fd;
279  for (it.toFirst();(fd=it.current());++it)
280  {
281  if (fd->hasDocumentation())
282  {
283  numFiles++;
284  }
285  }
286 
287  // write file list
288  if (numFiles>0)
289  {
290  ol.startMemberHeader("files");
291  ol.parseText(theTranslator->trFile(TRUE,FALSE));
292  ol.endMemberHeader();
293  ol.startMemberList();
294  QListIterator<FileDef> it(*m_fileList);
295  FileDef *fd;
296  for (;(fd=it.current());++it)
297  {
298  if (fd->hasDocumentation())
299  {
302  ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");
303  ol.insertMemberAlign();
304  if (fd->isLinkable())
305  {
306  ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
307  }
308  else
309  {
310  ol.startBold();
311  ol.docify(fd->name());
312  ol.endBold();
313  }
314  if (fd->generateSourceFile())
315  {
316  ol.pushGeneratorState();
318  ol.docify(" ");
319  ol.startTextLink(fd->includeName(),0);
320  ol.docify("[");
322  ol.docify("]");
323  ol.endTextLink();
324  ol.popGeneratorState();
325  }
326  ol.endMemberItem();
327  if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
328  {
331  FALSE, // indexWords
332  FALSE, // isExample
333  0, // exampleName
334  TRUE, // single line
335  TRUE // link from index
336  );
338  }
339  ol.endMemberDeclaration(0,0);
340  }
341  }
342  ol.endMemberList();
343  }
344 }
345 
347 {
348  ol.startMemberSections();
349 }
350 
352 {
353  ol.endMemberSections();
354 }
355 
356 QCString DirDef::shortTitle() const
357 {
359 }
360 
362 {
363  static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
364  return (!briefDescription().isEmpty() && repeatBrief) || !documentation().isEmpty();
365 }
366 
368 {
369  tagFile << " <compound kind=\"dir\">" << endl;
370  tagFile << " <name>" << convertToXML(displayName()) << "</name>" << endl;
371  tagFile << " <path>" << convertToXML(name()) << "</path>" << endl;
372  tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;
373  QListIterator<LayoutDocEntry> eli(
375  LayoutDocEntry *lde;
376  for (eli.toFirst();(lde=eli.current());++eli)
377  {
378  switch (lde->kind())
379  {
381  {
382  if (m_subdirs.count()>0)
383  {
384  DirDef *dd;
385  QListIterator<DirDef> it(m_subdirs);
386  for (;(dd=it.current());++it)
387  {
388  tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;
389  }
390  }
391  }
392  break;
394  {
395  if (m_fileList->count()>0)
396  {
397  QListIterator<FileDef> it(*m_fileList);
398  FileDef *fd;
399  for (;(fd=it.current());++it)
400  {
401  tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;
402  }
403  }
404  }
405  break;
406  default:
407  break;
408  }
409  }
410  writeDocAnchorsToTagFile(tagFile);
411  tagFile << " </compound>" << endl;
412 }
413 
415 {
416  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
417  ol.pushGeneratorState();
418 
419  QCString title=theTranslator->trDirReference(m_dispName);
420  startFile(ol,getOutputFileBase(),name(),title,HLI_Files,!generateTreeView);
421 
422  if (!generateTreeView)
423  {
424  // write navigation path
426  ol.endQuickIndices();
427  }
428 
430  ol.pushGeneratorState();
432  ol.parseText(shortTitle());
433  ol.enableAll();
435  ol.parseText(title);
436  ol.popGeneratorState();
437  endTitle(ol,getOutputFileBase(),title);
438  ol.startContents();
439 
440  //---------------------------------------- start flexible part -------------------------------
441 
442  SrcLangExt lang = getLanguage();
443  QListIterator<LayoutDocEntry> eli(
445  LayoutDocEntry *lde;
446  for (eli.toFirst();(lde=eli.current());++eli)
447  {
448  switch (lde->kind())
449  {
452  break;
455  break;
458  break;
460  writeSubDirList(ol);
461  break;
463  writeFileList(ol);
464  break;
467  break;
469  {
471  writeDetailedDescription(ol,ls->title(lang));
472  }
473  break;
507  err("Internal inconsistency: member %d should not be part of "
508  "LayoutDocManager::Directory entry list\n",lde->kind());
509  break;
510  }
511  }
512 
513  //---------------------------------------- end flexible part -------------------------------
514 
515  ol.endContents();
516 
517  endFileWithNavPath(this,ol);
518 
519  ol.popGeneratorState();
520 }
521 
523 {
524  if (m_level==-1) // level not set before
525  {
526  DirDef *p = parent();
527  if (p)
528  {
529  p->setLevel();
530  m_level = p->level()+1;
531  }
532  else
533  {
534  m_level = 0;
535  }
536  }
537 }
538 
543  FileDef *dstFd,bool inherited)
544 {
545  if (this==dir) return; // do not add self-dependencies
546  //static int count=0;
547  //printf(" %d add dependency %s->%s due to %s->%s\n",
548  // count++,shortName().data(),
549  // dir->shortName().data(),
550  // srcFd->name().data(),
551  // dstFd->name().data());
552 
553  // levels match => add direct dependency
554  bool added=FALSE;
555  UsedDir *usedDir = m_usedDirs->find(dir->getOutputFileBase());
556  if (usedDir) // dir dependency already present
557  {
558  FilePair *usedPair = usedDir->findFilePair(
559  srcFd->getOutputFileBase()+dstFd->getOutputFileBase());
560  if (usedPair==0) // new file dependency
561  {
562  //printf(" => new file\n");
563  usedDir->addFileDep(srcFd,dstFd);
564  added=TRUE;
565  }
566  else
567  {
568  // dir & file dependency already added
569  }
570  }
571  else // new directory dependency
572  {
573  //printf(" => new file\n");
574  usedDir = new UsedDir(dir,inherited);
575  usedDir->addFileDep(srcFd,dstFd);
576  m_usedDirs->insert(dir->getOutputFileBase(),usedDir);
577  added=TRUE;
578  }
579  if (added)
580  {
581  if (dir->parent())
582  {
583  // add relation to parent of used dir
584  addUsesDependency(dir->parent(),srcFd,dstFd,inherited);
585  }
586  if (parent())
587  {
588  // add relation for the parent of this dir as well
589  parent()->addUsesDependency(dir,srcFd,dstFd,TRUE);
590  }
591  }
592 }
593 
597 {
598  FileList *fl = m_fileList;
599  if (fl)
600  {
601  QListIterator<FileDef> fli(*fl);
602  FileDef *fd;
603  for (fli.toFirst();(fd=fli.current());++fli) // foreach file in dir dd
604  {
605  //printf(" File %s\n",fd->name().data());
606  //printf("** dir=%s file=%s\n",shortName().data(),fd->name().data());
607  QList<IncludeInfo> *ifl = fd->includeFileList();
608  if (ifl)
609  {
610  QListIterator<IncludeInfo> ifli(*ifl);
611  IncludeInfo *ii;
612  for (ifli.toFirst();(ii=ifli.current());++ifli) // foreach include file
613  {
614  //printf(" > %s\n",ii->includeName.data());
615  //printf(" #include %s\n",ii->includeName.data());
616  if (ii->fileDef && ii->fileDef->isLinkable()) // linkable file
617  {
618  DirDef *usedDir = ii->fileDef->getDirDef();
619  if (usedDir)
620  {
621  // add dependency: thisDir->usedDir
622  //static int count=0;
623  //printf(" %d: add dependency %s->%s\n",count++,name().data(),usedDir->name().data());
624  addUsesDependency(usedDir,fd,ii->fileDef,FALSE);
625  }
626  }
627  }
628  }
629  }
630  }
631  if (m_usedDirs)
632  {
633  QDictIterator<UsedDir> udi(*m_usedDirs);
634  UsedDir *udir;
635  for (udi.toFirst();(udir=udi.current());++udi)
636  {
637  udir->sort();
638  }
639  }
640 }
641 
642 bool DirDef::isParentOf(DirDef *dir) const
643 {
644  if (dir->parent()==this) // this is a parent of dir
645  return TRUE;
646  else if (dir->parent()) // repeat for the parent of dir
647  return isParentOf(dir->parent());
648  else
649  return FALSE;
650 }
651 
653 {
654  return m_usedDirs->count()==0;
655 }
656 
657 //----------------------------------------------------------------------
658 
659 int FilePairDict::compareValues(const FilePair *left,const FilePair *right) const
660 {
661  int orderHi = qstricmp(left->source()->name(),right->source()->name());
662  if (orderHi!=0) return orderHi;
663  int orderLo = qstricmp(left->destination()->name(),right->destination()->name());
664  return orderLo;
665 }
666 
667 //----------------------------------------------------------------------
668 
669 UsedDir::UsedDir(DirDef *dir,bool inherited) :
670  m_dir(dir), m_filePairs(7), m_inherited(inherited)
671 {
673 }
674 
676 {
677 }
678 
679 
681 {
683  new FilePair(srcFd,dstFd));
684 }
685 
687 {
688  m_filePairs.sort();
689 }
690 
691 FilePair *UsedDir::findFilePair(const char *name)
692 {
693  QCString n=name;
694  return n.isEmpty() ? 0 : m_filePairs.find(n);
695 }
696 
697 DirDef *DirDef::createNewDir(const char *path)
698 {
699  ASSERT(path!=0);
700  DirDef *dir = Doxygen::directories->find(path);
701  if (dir==0) // new dir
702  {
703  //printf("Adding new dir %s\n",path);
704  dir = new DirDef(path);
705  //printf("createNewDir %s short=%s\n",path,dir->shortName().data());
706  Doxygen::directories->append(path,dir);
707  }
708  return dir;
709 }
710 
711 bool DirDef::matchPath(const QCString &path,QStrList &l)
712 {
713  const char *s=l.first();
714  while (s)
715  {
716  QCString prefix = s;
717  if (qstricmp(prefix.left(path.length()),path)==0) // case insensitive compare
718  {
719  return TRUE;
720  }
721  s = l.next();
722  }
723  return FALSE;
724 }
725 
729 DirDef *DirDef::mergeDirectoryInTree(const QCString &path)
730 {
731  //printf("DirDef::mergeDirectoryInTree(%s)\n",path.data());
732  int p=0,i=0;
733  DirDef *dir=0;
734  while ((i=path.find('/',p))!=-1)
735  {
736  QCString part=path.left(i+1);
737  if (!matchPath(part,Config_getList(STRIP_FROM_PATH)) && (part!="/" && part!="//"))
738  {
739  dir=createNewDir(part);
740  }
741  p=i+1;
742  }
743  return dir;
744 }
745 
746 //----------------------------------------------------------------------
747 
748 static void writePartialDirPath(OutputList &ol,const DirDef *root,const DirDef *target)
749 {
750  if (target->parent()!=root)
751  {
752  writePartialDirPath(ol,root,target->parent());
753  ol.writeString("&#160;/&#160;");
754  }
755  ol.writeObjectLink(target->getReference(),target->getOutputFileBase(),0,target->shortName());
756 }
757 
758 static void writePartialFilePath(OutputList &ol,const DirDef *root,const FileDef *fd)
759 {
760  if (fd->getDirDef() && fd->getDirDef()!=root)
761  {
762  writePartialDirPath(ol,root,fd->getDirDef());
763  ol.writeString("&#160;/&#160;");
764  }
765  if (fd->isLinkable())
766  {
767  ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());
768  }
769  else
770  {
771  ol.startBold();
772  ol.docify(fd->name());
773  ol.endBold();
774  }
775 }
776 
778 {
779  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
780  ol.pushGeneratorState();
782 
783  QCString shortTitle=theTranslator->trDirRelation(
784  m_src->shortName()+" &rarr; "+
785  m_dst->dir()->shortName());
786  QCString title=theTranslator->trDirRelation(
787  m_src->displayName()+" -> "+
788  m_dst->dir()->shortName());
790  title,HLI_None,!generateTreeView,m_src->getOutputFileBase());
791 
792  if (!generateTreeView)
793  {
794  // write navigation path
796  ol.endQuickIndices();
797  }
798  ol.startContents();
799 
800  ol.writeString("<h3>"+shortTitle+"</h3>");
801  ol.writeString("<table class=\"dirtab\">");
802  ol.writeString("<tr class=\"dirtab\">");
803  ol.writeString("<th class=\"dirtab\">");
805  ol.writeString("</th>");
806  ol.writeString("<th class=\"dirtab\">");
808  ol.writeString("</th>");
809  ol.writeString("</tr>");
810 
812  FilePair *fp;
813  for (fpi.toFirst();(fp=fpi.current());++fpi)
814  {
815  ol.writeString("<tr class=\"dirtab\">");
816  ol.writeString("<td class=\"dirtab\">");
817  writePartialFilePath(ol,m_src,fp->source());
818  ol.writeString("</td>");
819  ol.writeString("<td class=\"dirtab\">");
820  writePartialFilePath(ol,m_dst->dir(),fp->destination());
821  ol.writeString("</td>");
822  ol.writeString("</tr>");
823  }
824  ol.writeString("</table>");
825 
826  ol.endContents();
827 
829 
830  ol.popGeneratorState();
831 }
832 
833 //----------------------------------------------------------------------
834 // external functions
835 
840 {
841  QCString path;
842  DirDef *dir;
844  if (Doxygen::directories->count()>0) // we have at least one dir
845  {
846  // start will full path of first dir
847  sdi.toFirst();
848  dir=sdi.current();
849  path=dir->name();
850  int i=path.findRev('/',path.length()-2);
851  path=path.left(i+1);
852  bool done=FALSE;
853  if (i==-1)
854  {
855  path="";
856  }
857  else
858  {
859  while (!done)
860  {
861  int l = path.length();
862  int count=0;
863  for (sdi.toFirst();(dir=sdi.current());++sdi)
864  {
865  QCString dirName = dir->name();
866  if (dirName.length()>path.length())
867  {
868  if (qstrncmp(dirName,path,l)!=0) // dirName does not start with path
869  {
870  int i=path.findRev('/',l-2);
871  if (i==-1) // no unique prefix -> stop
872  {
873  path="";
874  done=TRUE;
875  }
876  else // restart with shorter path
877  {
878  path=path.left(i+1);
879  break;
880  }
881  }
882  }
883  else // dir is shorter than path -> take path of dir as new start
884  {
885  path=dir->name();
886  l=path.length();
887  int i=path.findRev('/',l-2);
888  if (i==-1) // no unique prefix -> stop
889  {
890  path="";
891  done=TRUE;
892  }
893  else // restart with shorter path
894  {
895  path=path.left(i+1);
896  }
897  break;
898  }
899  count++;
900  }
901  if (count==Doxygen::directories->count())
902  // path matches for all directories -> found the common prefix
903  {
904  done=TRUE;
905  }
906  }
907  }
908  }
909  for (sdi.toFirst();(dir=sdi.current());++sdi)
910  {
911  QCString diskName = dir->name().right(dir->name().length()-path.length());
912  dir->setDiskName(diskName);
913  //printf("set disk name: %s -> %s\n",dir->name().data(),diskName.data());
914  }
915 }
916 
918 {
919  // for each input file
921  FileName *fn;
922  for (fnli.toFirst();(fn=fnli.current());++fnli)
923  {
924  FileNameIterator fni(*fn);
925  FileDef *fd;
926  for (;(fd=fni.current());++fni)
927  {
928  //printf("buildDirectories %s\n",fd->name().data());
929  if (fd->getReference().isEmpty() && !fd->isDocumentationFile())
930  {
931  DirDef *dir;
932  if ((dir=Doxygen::directories->find(fd->getPath()))==0) // new directory
933  {
935  }
936  if (dir) dir->addFile(fd);
937  }
938  else
939  {
940  // do something for file imported via tag files.
941  }
942  }
943  }
944 
945  //DirDef *root = new DirDef("root:");
946  // compute relations between directories => introduce container dirs.
947  DirDef *dir;
949  for (sdi.toFirst();(dir=sdi.current());++sdi)
950  {
951  QCString name = dir->name();
952  int i=name.findRev('/',name.length()-2);
953  if (i>0)
954  {
955  DirDef *parent = Doxygen::directories->find(name.left(i+1));
956  //if (parent==0) parent=root;
957  if (parent)
958  {
959  parent->addSubDir(dir);
960  //printf("DirDef::addSubdir(): Adding subdir\n%s to\n%s\n",
961  // dir->displayName().data(), parent->displayName().data());
962  }
963  }
964  }
965  for (sdi.toFirst();(dir=sdi.current());++sdi)
966  {
967  dir->sort();
968  }
971 }
972 
974 {
975  DirDef *dir;
977  // compute nesting level for each directory
978  for (sdi.toFirst();(dir=sdi.current());++sdi)
979  {
980  dir->setLevel();
981  }
982  // compute uses dependencies between directories
983  for (sdi.toFirst();(dir=sdi.current());++sdi)
984  {
985  //printf("computeDependencies for %s: #dirs=%d\n",dir->name().data(),Doxygen::directories.count());
986  dir->computeDependencies();
987  }
988 
989 }
990 
992 {
993  DirDef *dir;
995  for (sdi.toFirst();(dir=sdi.current());++sdi)
996  {
997  dir->writeDocumentation(ol);
998  }
999  if (Config_getBool(DIRECTORY_GRAPH))
1000  {
1002  DirRelation *dr;
1003  for (rdi.toFirst();(dr=rdi.current());++rdi)
1004  {
1005  dr->writeDocumentation(ol);
1006  }
1007  }
1008 }
1009