|
1 /****************************************************************************** |
|
2 * |
|
3 * |
|
4 * |
|
5 * Copyright (C) 1997-2008 by Dimitri van Heesch. |
|
6 * |
|
7 * Permission to use, copy, modify, and distribute this software and its |
|
8 * documentation under the terms of the GNU General Public License is hereby |
|
9 * granted. No representations are made about the suitability of this software |
|
10 * for any purpose. It is provided "as is" without express or implied warranty. |
|
11 * See the GNU General Public License for more details. |
|
12 * |
|
13 * Documents produced by Doxygen are derivative works derived from the |
|
14 * input used in their production; they are not affected by this license. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "qtbc.h" |
|
19 #include "memberlist.h" |
|
20 #include "classlist.h" |
|
21 #include "filedef.h" |
|
22 #include "doxygen.h" |
|
23 #include "memberdef.h" |
|
24 #include "classdef.h" |
|
25 #include "namespacedef.h" |
|
26 #include "util.h" |
|
27 #include "language.h" |
|
28 #include "outputlist.h" |
|
29 #include "dot.h" |
|
30 #include "message.h" |
|
31 #include "docparser.h" |
|
32 #include "searchindex.h" |
|
33 #include "htags.h" |
|
34 #include "parserintf.h" |
|
35 #include "portable.h" |
|
36 #include "vhdldocgen.h" |
|
37 #include "debug.h" |
|
38 #include "layout.h" |
|
39 |
|
40 //--------------------------------------------------------------------------- |
|
41 |
|
42 class DevNullCodeDocInterface : public CodeOutputInterface |
|
43 { |
|
44 public: |
|
45 virtual void codify(const char *) {} |
|
46 virtual void writeCodeLink(const char *,const char *, |
|
47 const char *,const char *, |
|
48 const char *) {} |
|
49 virtual void writeLineNumber(const char *,const char *, |
|
50 const char *,int) {} |
|
51 virtual void startCodeLine() {} |
|
52 virtual void endCodeLine() {} |
|
53 virtual void startCodeAnchor(const char *) {} |
|
54 virtual void endCodeAnchor() {} |
|
55 virtual void startFontClass(const char *) {} |
|
56 virtual void endFontClass() {} |
|
57 virtual void writeCodeAnchor(const char *) {} |
|
58 virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} |
|
59 }; |
|
60 |
|
61 //--------------------------------------------------------------------------- |
|
62 |
|
63 /*! create a new file definition, where \a p is the file path, |
|
64 \a nm the file name, and \a ref is an HTML anchor name if the |
|
65 file was read from a tag file or 0 otherwise |
|
66 */ |
|
67 FileDef::FileDef(const char *p,const char *nm, |
|
68 const char *lref,const char *dn) |
|
69 : Definition((QCString)p+nm,1,nm) |
|
70 { |
|
71 path=p; |
|
72 filepath=path+nm; |
|
73 filename=nm; |
|
74 diskname=dn; |
|
75 if (diskname.isEmpty()) diskname=nm; |
|
76 setReference(lref); |
|
77 classSDict = 0; |
|
78 includeList = 0; |
|
79 includeDict = 0; |
|
80 includedByList = 0; |
|
81 includedByDict = 0; |
|
82 namespaceSDict = 0; |
|
83 srcDefDict = 0; |
|
84 srcMemberDict = 0; |
|
85 usingDirList = 0; |
|
86 usingDeclList = 0; |
|
87 package = 0; |
|
88 isSource = FALSE; |
|
89 docname = nm; |
|
90 dir = 0; |
|
91 if (Config_getBool("FULL_PATH_NAMES")) |
|
92 { |
|
93 docname.prepend(stripFromPath(path.copy())); |
|
94 } |
|
95 m_isJava = name().right(5)==".java"; |
|
96 memberGroupSDict = 0; |
|
97 acquireFileVersion(); |
|
98 m_subGrouping=Config_getBool("SUBGROUPING"); |
|
99 } |
|
100 |
|
101 /*! destroy the file definition */ |
|
102 FileDef::~FileDef() |
|
103 { |
|
104 delete classSDict; |
|
105 delete includeDict; |
|
106 delete includeList; |
|
107 delete includedByDict; |
|
108 delete includedByList; |
|
109 delete namespaceSDict; |
|
110 delete srcDefDict; |
|
111 delete srcMemberDict; |
|
112 delete usingDirList; |
|
113 delete usingDeclList; |
|
114 delete memberGroupSDict; |
|
115 } |
|
116 |
|
117 /*! Compute the HTML anchor names for all members in the class */ |
|
118 void FileDef::computeAnchors() |
|
119 { |
|
120 MemberList *ml = getMemberList(MemberList::allMembersList); |
|
121 if (ml) setAnchors(0,'a',ml); |
|
122 } |
|
123 |
|
124 void FileDef::distributeMemberGroupDocumentation() |
|
125 { |
|
126 //printf("FileDef::distributeMemberGroupDocumentation()\n"); |
|
127 if (memberGroupSDict) |
|
128 { |
|
129 MemberGroupSDict::Iterator mgli(*memberGroupSDict); |
|
130 MemberGroup *mg; |
|
131 for (;(mg=mgli.current());++mgli) |
|
132 { |
|
133 mg->distributeMemberGroupDocumentation(); |
|
134 } |
|
135 } |
|
136 } |
|
137 |
|
138 void FileDef::findSectionsInDocumentation() |
|
139 { |
|
140 docFindSections(documentation(),this,0,docFile()); |
|
141 if (memberGroupSDict) |
|
142 { |
|
143 MemberGroupSDict::Iterator mgli(*memberGroupSDict); |
|
144 MemberGroup *mg; |
|
145 for (;(mg=mgli.current());++mgli) |
|
146 { |
|
147 mg->findSectionsInDocumentation(); |
|
148 } |
|
149 } |
|
150 |
|
151 QListIterator<MemberList> mli(m_memberLists); |
|
152 MemberList *ml; |
|
153 for (mli.toFirst();(ml=mli.current());++mli) |
|
154 { |
|
155 if (ml->listType()&MemberList::declarationLists) |
|
156 { |
|
157 ml->findSectionsInDocumentation(); |
|
158 } |
|
159 } |
|
160 } |
|
161 |
|
162 void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title) |
|
163 { |
|
164 if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || |
|
165 !documentation().isEmpty() || |
|
166 (Config_getBool("SOURCE_BROWSER") && getStartBodyLine()!=-1 && getBodyDef()) |
|
167 ) |
|
168 { |
|
169 ol.writeRuler(); |
|
170 ol.pushGeneratorState(); |
|
171 ol.disableAllBut(OutputGenerator::Html); |
|
172 ol.writeAnchor(0,"_details"); |
|
173 ol.popGeneratorState(); |
|
174 ol.startGroupHeader(); |
|
175 ol.parseText(title); |
|
176 ol.endGroupHeader(); |
|
177 |
|
178 ol.startTextBlock(); |
|
179 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) |
|
180 { |
|
181 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); |
|
182 } |
|
183 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && |
|
184 !documentation().isEmpty()) |
|
185 { |
|
186 ol.pushGeneratorState(); |
|
187 ol.disable(OutputGenerator::Man); |
|
188 ol.disable(OutputGenerator::RTF); |
|
189 // ol.newParagraph(); // FIXME:PARA |
|
190 ol.enableAll(); |
|
191 ol.disableAllBut(OutputGenerator::Man); |
|
192 ol.writeString("\n\n"); |
|
193 ol.popGeneratorState(); |
|
194 } |
|
195 if (!documentation().isEmpty()) |
|
196 { |
|
197 ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); |
|
198 } |
|
199 //printf("Writing source ref for file %s\n",name().data()); |
|
200 if (Config_getBool("SOURCE_BROWSER")) |
|
201 { |
|
202 ol.startParagraph(); |
|
203 QCString refText = theTranslator->trDefinedInSourceFile(); |
|
204 int fileMarkerPos = refText.find("@0"); |
|
205 if (fileMarkerPos!=-1) // should always pass this. |
|
206 { |
|
207 ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1 |
|
208 ol.writeObjectLink(0,getSourceFileBase(), |
|
209 0,name()); |
|
210 ol.parseText(refText.right( |
|
211 refText.length()-fileMarkerPos-2)); // text right from marker 2 |
|
212 } |
|
213 ol.endParagraph(); |
|
214 } |
|
215 ol.endTextBlock(); |
|
216 } |
|
217 } |
|
218 |
|
219 void FileDef::writeBriefDescription(OutputList &ol) |
|
220 { |
|
221 if (!briefDescription().isEmpty()) |
|
222 { |
|
223 ol.startParagraph(); |
|
224 ol.parseDoc(briefFile(),briefLine(),this,0, |
|
225 briefDescription(),TRUE,FALSE,0,TRUE,FALSE); |
|
226 ol.pushGeneratorState(); |
|
227 ol.disable(OutputGenerator::RTF); |
|
228 ol.writeString(" \n"); |
|
229 ol.enable(OutputGenerator::RTF); |
|
230 |
|
231 if (Config_getBool("REPEAT_BRIEF") || |
|
232 !documentation().isEmpty() |
|
233 ) |
|
234 { |
|
235 ol.disableAllBut(OutputGenerator::Html); |
|
236 ol.startTextLink(0,"_details"); |
|
237 ol.parseText(theTranslator->trMore()); |
|
238 ol.endTextLink(); |
|
239 } |
|
240 ol.popGeneratorState(); |
|
241 ol.endParagraph(); |
|
242 |
|
243 //ol.pushGeneratorState(); |
|
244 //ol.disable(OutputGenerator::RTF); |
|
245 //ol.newParagraph(); |
|
246 //ol.popGeneratorState(); |
|
247 } |
|
248 ol.writeSynopsis(); |
|
249 } |
|
250 |
|
251 void FileDef::writeIncludeFiles(OutputList &ol) |
|
252 { |
|
253 if (/*Config_getBool("SHOW_INCLUDE_FILES") &&*/ includeList && |
|
254 includeList->count()>0) |
|
255 { |
|
256 ol.startTextBlock(TRUE); |
|
257 QListIterator<IncludeInfo> ili(*includeList); |
|
258 IncludeInfo *ii; |
|
259 for (;(ii=ili.current());++ili) |
|
260 { |
|
261 FileDef *fd=ii->fileDef; |
|
262 bool isIDLorJava = FALSE; |
|
263 if (fd) |
|
264 { |
|
265 isIDLorJava = fd->name().right(4)==".idl" || // M$ or Corba IDL |
|
266 fd->name().right(5)==".pidl" || |
|
267 fd->name().right(5)==".java" || // Sun's Java |
|
268 fd->name().right(4)==".jsl"; // M$ J# |
|
269 } |
|
270 ol.startTypewriter(); |
|
271 if (isIDLorJava) // IDL/Java include |
|
272 { |
|
273 ol.docify("import "); |
|
274 } |
|
275 else if (ii->imported) // Objective-C include |
|
276 { |
|
277 ol.docify("#import "); |
|
278 } |
|
279 else // C/C++ include |
|
280 { |
|
281 ol.docify("#include "); |
|
282 } |
|
283 if (ii->local || isIDLorJava) |
|
284 ol.docify("\""); |
|
285 else |
|
286 ol.docify("<"); |
|
287 ol.disable(OutputGenerator::Html); |
|
288 ol.docify(ii->includeName); |
|
289 ol.enableAll(); |
|
290 ol.disableAllBut(OutputGenerator::Html); |
|
291 |
|
292 // Here we use the include file name as it appears in the file. |
|
293 // we could also we the name as it is used within doxygen, |
|
294 // then we should have used fd->docName() instead of ii->includeName |
|
295 if (fd && fd->isLinkable()) |
|
296 { |
|
297 ol.writeObjectLink(fd->getReference(), |
|
298 fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(), |
|
299 0,ii->includeName); |
|
300 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fd->isReference()) |
|
301 { |
|
302 const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no"; |
|
303 const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no"; |
|
304 Doxygen::tagFile << " <includes id=\"" |
|
305 << convertToXML(fd->getOutputFileBase()) << "\" " |
|
306 << "name=\"" << convertToXML(fd->name()) << "\" " |
|
307 << "local=\"" << locStr << "\" " |
|
308 << "imported=\"" << impStr << "\">" |
|
309 << convertToXML(ii->includeName) |
|
310 << "</includes>" |
|
311 << endl; |
|
312 } |
|
313 } |
|
314 else |
|
315 { |
|
316 ol.docify(ii->includeName); |
|
317 } |
|
318 |
|
319 ol.enableAll(); |
|
320 if (ii->local || isIDLorJava) |
|
321 ol.docify("\""); |
|
322 else |
|
323 ol.docify(">"); |
|
324 if (isIDLorJava) |
|
325 ol.docify(";"); |
|
326 ol.endTypewriter(); |
|
327 ol.lineBreak(); |
|
328 } |
|
329 ol.endTextBlock(); |
|
330 } |
|
331 } |
|
332 |
|
333 void FileDef::writeIncludeGraph(OutputList &ol) |
|
334 { |
|
335 if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDE_GRAPH")*/) |
|
336 { |
|
337 //printf("Graph for file %s\n",name().data()); |
|
338 DotInclDepGraph incDepGraph(this,FALSE); |
|
339 if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) |
|
340 { |
|
341 ol.startTextBlock(); |
|
342 ol.disable(OutputGenerator::Man); |
|
343 ol.startInclDepGraph(); |
|
344 ol.parseText(theTranslator->trInclDepGraph(name())); |
|
345 ol.endInclDepGraph(incDepGraph); |
|
346 ol.enableAll(); |
|
347 ol.endTextBlock(TRUE); |
|
348 } |
|
349 //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); |
|
350 } |
|
351 } |
|
352 |
|
353 void FileDef::writeIncludedByGraph(OutputList &ol) |
|
354 { |
|
355 if (Config_getBool("HAVE_DOT") /*&& Config_getBool("INCLUDED_BY_GRAPH")*/) |
|
356 { |
|
357 //printf("Graph for file %s\n",name().data()); |
|
358 DotInclDepGraph incDepGraph(this,TRUE); |
|
359 if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) |
|
360 { |
|
361 ol.startTextBlock(); |
|
362 ol.disable(OutputGenerator::Man); |
|
363 ol.startInclDepGraph(); |
|
364 ol.parseText(theTranslator->trInclByDepGraph()); |
|
365 ol.endInclDepGraph(incDepGraph); |
|
366 ol.enableAll(); |
|
367 ol.endTextBlock(TRUE); |
|
368 } |
|
369 //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); |
|
370 } |
|
371 } |
|
372 |
|
373 |
|
374 void FileDef::writeSourceLink(OutputList &ol) |
|
375 { |
|
376 //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile()); |
|
377 if (generateSourceFile()) |
|
378 { |
|
379 ol.disableAllBut(OutputGenerator::Html); |
|
380 ol.startParagraph(); |
|
381 ol.startTextLink(includeName(),0); |
|
382 ol.parseText(theTranslator->trGotoSourceCode()); |
|
383 ol.endTextLink(); |
|
384 ol.endParagraph(); |
|
385 ol.enableAll(); |
|
386 } |
|
387 } |
|
388 |
|
389 void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title) |
|
390 { |
|
391 // write list of namespaces |
|
392 if (namespaceSDict) namespaceSDict->writeDeclaration(ol,title); |
|
393 } |
|
394 |
|
395 void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title) |
|
396 { |
|
397 // write list of classes |
|
398 if (classSDict) classSDict->writeDeclaration(ol,0,title,FALSE); |
|
399 } |
|
400 |
|
401 void FileDef::startMemberDeclarations(OutputList &ol) |
|
402 { |
|
403 ol.startMemberSections(); |
|
404 } |
|
405 |
|
406 void FileDef::endMemberDeclarations(OutputList &ol) |
|
407 { |
|
408 ol.endMemberSections(); |
|
409 } |
|
410 |
|
411 void FileDef::startMemberDocumentation(OutputList &ol) |
|
412 { |
|
413 if (Config_getBool("SEPARATE_MEMBER_PAGES")) |
|
414 { |
|
415 ol.disable(OutputGenerator::Html); |
|
416 Doxygen::suppressDocWarnings = TRUE; |
|
417 } |
|
418 } |
|
419 |
|
420 void FileDef::endMemberDocumentation(OutputList &ol) |
|
421 { |
|
422 if (Config_getBool("SEPARATE_MEMBER_PAGES")) |
|
423 { |
|
424 ol.enable(OutputGenerator::Html); |
|
425 Doxygen::suppressDocWarnings = FALSE; |
|
426 } |
|
427 } |
|
428 |
|
429 void FileDef::writeMemberGroups(OutputList &ol) |
|
430 { |
|
431 /* write user defined member groups */ |
|
432 if (memberGroupSDict) |
|
433 { |
|
434 MemberGroupSDict::Iterator mgli(*memberGroupSDict); |
|
435 MemberGroup *mg; |
|
436 for (;(mg=mgli.current());++mgli) |
|
437 { |
|
438 if ((!mg->allMembersInSameSection() || !m_subGrouping) |
|
439 && mg->header()!="[NOHEADER]") |
|
440 { |
|
441 mg->writeDeclarations(ol,0,0,this,0); |
|
442 } |
|
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 void FileDef::writeAuthorSection(OutputList &ol) |
|
448 { |
|
449 // write Author section (Man only) |
|
450 ol.pushGeneratorState(); |
|
451 ol.disableAllBut(OutputGenerator::Man); |
|
452 ol.startGroupHeader(); |
|
453 ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); |
|
454 ol.endGroupHeader(); |
|
455 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); |
|
456 ol.popGeneratorState(); |
|
457 } |
|
458 |
|
459 /*! Write the documentation page for this file to the file of output |
|
460 generators \a ol. |
|
461 */ |
|
462 void FileDef::writeDocumentation(OutputList &ol) |
|
463 { |
|
464 //funcList->countDecMembers(); |
|
465 |
|
466 //QCString fn = name(); |
|
467 //if (Config_getBool("FULL_PATH_NAMES")) |
|
468 //{ |
|
469 // fn.prepend(stripFromPath(getPath().copy())); |
|
470 //} |
|
471 |
|
472 //printf("WriteDocumentation diskname=%s\n",diskname.data()); |
|
473 |
|
474 QCString versionTitle; |
|
475 if (!fileVersion.isEmpty()) |
|
476 { |
|
477 versionTitle=("("+fileVersion+")"); |
|
478 } |
|
479 QCString title = docname+versionTitle; |
|
480 QCString pageTitle=theTranslator->trFileReference(docname); |
|
481 |
|
482 if (Config_getBool("SHOW_DIRECTORIES") && getDirDef()) |
|
483 { |
|
484 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,TRUE); |
|
485 getDirDef()->writeNavigationPath(ol); |
|
486 ol.endQuickIndices(); |
|
487 ol.startContents(); |
|
488 QCString pageTitleShort=theTranslator->trFileReference(name()); |
|
489 startTitle(ol,getOutputFileBase()); |
|
490 ol.pushGeneratorState(); |
|
491 ol.disableAllBut(OutputGenerator::Html); |
|
492 ol.parseText(pageTitleShort); // Html only |
|
493 ol.enableAll(); |
|
494 ol.disable(OutputGenerator::Html); |
|
495 ol.parseText(pageTitle); // other output formats |
|
496 ol.popGeneratorState(); |
|
497 addGroupListToTitle(ol,this); |
|
498 endTitle(ol,getOutputFileBase(),title); |
|
499 } |
|
500 else |
|
501 { |
|
502 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible); |
|
503 startTitle(ol,getOutputFileBase()); |
|
504 ol.parseText(pageTitle); |
|
505 addGroupListToTitle(ol,this); |
|
506 endTitle(ol,getOutputFileBase(),title); |
|
507 } |
|
508 if (!fileVersion.isEmpty()) |
|
509 { |
|
510 ol.disableAllBut(OutputGenerator::Html); |
|
511 ol.startProjectNumber(); |
|
512 ol.docify(versionTitle); |
|
513 ol.endProjectNumber(); |
|
514 ol.enableAll(); |
|
515 } |
|
516 |
|
517 if (Doxygen::searchIndex) |
|
518 { |
|
519 Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase()); |
|
520 Doxygen::searchIndex->addWord(localName(),TRUE); |
|
521 } |
|
522 |
|
523 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) |
|
524 { |
|
525 Doxygen::tagFile << " <compound kind=\"file\">" << endl; |
|
526 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; |
|
527 Doxygen::tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl; |
|
528 Doxygen::tagFile << " <filename>" |
|
529 << convertToXML(getOutputFileBase()) |
|
530 << "</filename>" << endl; |
|
531 } |
|
532 |
|
533 //---------------------------------------- start flexible part ------------------------------- |
|
534 |
|
535 QListIterator<LayoutDocEntry> eli( |
|
536 LayoutDocManager::instance().docEntries(LayoutDocManager::File)); |
|
537 LayoutDocEntry *lde; |
|
538 for (eli.toFirst();(lde=eli.current());++eli) |
|
539 { |
|
540 switch (lde->kind()) |
|
541 { |
|
542 case LayoutDocEntry::BriefDesc: |
|
543 writeBriefDescription(ol); |
|
544 break; |
|
545 case LayoutDocEntry::MemberDeclStart: |
|
546 startMemberDeclarations(ol); |
|
547 break; |
|
548 case LayoutDocEntry::FileIncludes: |
|
549 writeIncludeFiles(ol); |
|
550 break; |
|
551 case LayoutDocEntry::FileIncludeGraph: |
|
552 writeIncludeGraph(ol); |
|
553 break; |
|
554 case LayoutDocEntry::FileIncludedByGraph: |
|
555 writeIncludedByGraph(ol); |
|
556 break; |
|
557 case LayoutDocEntry::FileSourceLink: |
|
558 writeSourceLink(ol); |
|
559 break; |
|
560 case LayoutDocEntry::FileClasses: |
|
561 { |
|
562 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; |
|
563 writeClassDeclarations(ol,ls->title); |
|
564 } |
|
565 break; |
|
566 case LayoutDocEntry::FileNamespaces: |
|
567 { |
|
568 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; |
|
569 writeNamespaceDeclarations(ol,ls->title); |
|
570 } |
|
571 break; |
|
572 case LayoutDocEntry::MemberGroups: |
|
573 writeMemberGroups(ol); |
|
574 break; |
|
575 case LayoutDocEntry::MemberDecl: |
|
576 { |
|
577 LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; |
|
578 writeMemberDeclarations(ol,lmd->type,lmd->title); |
|
579 } |
|
580 break; |
|
581 case LayoutDocEntry::MemberDeclEnd: |
|
582 endMemberDeclarations(ol); |
|
583 break; |
|
584 case LayoutDocEntry::DetailedDesc: |
|
585 { |
|
586 LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; |
|
587 writeDetailedDescription(ol,ls->title); |
|
588 } |
|
589 break; |
|
590 case LayoutDocEntry::MemberDefStart: |
|
591 startMemberDocumentation(ol); |
|
592 break; |
|
593 case LayoutDocEntry::MemberDef: |
|
594 { |
|
595 LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; |
|
596 writeMemberDocumentation(ol,lmd->type,lmd->title); |
|
597 } |
|
598 break; |
|
599 case LayoutDocEntry::MemberDefEnd: |
|
600 endMemberDocumentation(ol); |
|
601 break; |
|
602 case LayoutDocEntry::AuthorSection: |
|
603 writeAuthorSection(ol); |
|
604 break; |
|
605 case LayoutDocEntry::ClassIncludes: |
|
606 case LayoutDocEntry::ClassInheritanceGraph: |
|
607 case LayoutDocEntry::ClassNestedClasses: |
|
608 case LayoutDocEntry::ClassCollaborationGraph: |
|
609 case LayoutDocEntry::ClassAllMembersLink: |
|
610 case LayoutDocEntry::ClassUsedFiles: |
|
611 case LayoutDocEntry::NamespaceNestedNamespaces: |
|
612 case LayoutDocEntry::NamespaceClasses: |
|
613 case LayoutDocEntry::GroupClasses: |
|
614 case LayoutDocEntry::GroupNamespaces: |
|
615 case LayoutDocEntry::GroupDirs: |
|
616 case LayoutDocEntry::GroupNestedGroups: |
|
617 case LayoutDocEntry::GroupFiles: |
|
618 case LayoutDocEntry::GroupGraph: |
|
619 case LayoutDocEntry::GroupPageDocs: |
|
620 case LayoutDocEntry::DirSubDirs: |
|
621 case LayoutDocEntry::DirFiles: |
|
622 case LayoutDocEntry::DirGraph: |
|
623 err("Internal inconsistency: member %d should not be part of " |
|
624 "LayoutDocManager::File entry list\n",lde->kind()); |
|
625 break; |
|
626 } |
|
627 } |
|
628 |
|
629 //---------------------------------------- end flexible part ------------------------------- |
|
630 |
|
631 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) |
|
632 { |
|
633 writeDocAnchorsToTagFile(); |
|
634 Doxygen::tagFile << " </compound>" << endl; |
|
635 } |
|
636 |
|
637 endFile(ol); |
|
638 |
|
639 if (Config_getBool("SEPARATE_MEMBER_PAGES")) |
|
640 { |
|
641 MemberList *ml = getMemberList(MemberList::allMembersList); |
|
642 if (ml) ml->sort(); |
|
643 writeMemberPages(ol); |
|
644 } |
|
645 } |
|
646 |
|
647 void FileDef::writeMemberPages(OutputList &ol) |
|
648 { |
|
649 ol.pushGeneratorState(); |
|
650 ol.disableAllBut(OutputGenerator::Html); |
|
651 |
|
652 QListIterator<MemberList> mli(m_memberLists); |
|
653 MemberList *ml; |
|
654 for (mli.toFirst();(ml=mli.current());++mli) |
|
655 { |
|
656 if (ml->listType()&MemberList::documentationLists) |
|
657 { |
|
658 ml->writeDocumentationPage(ol,name(),this); |
|
659 } |
|
660 } |
|
661 |
|
662 ol.popGeneratorState(); |
|
663 } |
|
664 |
|
665 void FileDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const |
|
666 { |
|
667 static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); |
|
668 |
|
669 ol.writeString(" <div class=\"navtab\">\n"); |
|
670 ol.writeString(" <table>\n"); |
|
671 |
|
672 MemberList *allMemberList = getMemberList(MemberList::allMembersList); |
|
673 if (allMemberList) |
|
674 { |
|
675 MemberListIterator mli(*allMemberList); |
|
676 MemberDef *md; |
|
677 for (mli.toFirst();(md=mli.current());++mli) |
|
678 { |
|
679 if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable()) |
|
680 { |
|
681 ol.writeString(" <tr><td class=\"navtab\">"); |
|
682 if (md->isLinkableInProject()) |
|
683 { |
|
684 if (md==currentMd) // selected item => highlight |
|
685 { |
|
686 ol.writeString("<a class=\"qindexHL\" "); |
|
687 } |
|
688 else |
|
689 { |
|
690 ol.writeString("<a class=\"qindex\" "); |
|
691 } |
|
692 ol.writeString("href=\""); |
|
693 if (createSubDirs) ol.writeString("../../"); |
|
694 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); |
|
695 ol.writeString("\">"); |
|
696 ol.writeString(md->localName()); |
|
697 ol.writeString("</a>"); |
|
698 } |
|
699 ol.writeString("</td></tr>\n"); |
|
700 } |
|
701 } |
|
702 } |
|
703 |
|
704 ol.writeString(" </table>\n"); |
|
705 ol.writeString(" </div>\n"); |
|
706 } |
|
707 |
|
708 /*! Write a source listing of this file to the output */ |
|
709 void FileDef::writeSource(OutputList &ol) |
|
710 { |
|
711 static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); |
|
712 static bool latexSourceCode = Config_getBool("LATEX_SOURCE_CODE"); |
|
713 QCString title = docname; |
|
714 if (!fileVersion.isEmpty()) |
|
715 { |
|
716 title+=(" ("+fileVersion+")"); |
|
717 } |
|
718 QCString pageTitle = theTranslator->trSourceFile(title); |
|
719 ol.disable(OutputGenerator::Man); |
|
720 ol.disable(OutputGenerator::RTF); |
|
721 if (!latexSourceCode) ol.disable(OutputGenerator::Latex); |
|
722 |
|
723 if (Config_getBool("SHOW_DIRECTORIES") && getDirDef()) |
|
724 { |
|
725 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE); |
|
726 getDirDef()->writeNavigationPath(ol); |
|
727 ol.endQuickIndices(); |
|
728 ol.startContents(); |
|
729 startTitle(ol,getOutputFileBase()); |
|
730 ol.parseText(name()); |
|
731 endTitle(ol,getOutputFileBase(),title); |
|
732 } |
|
733 else |
|
734 { |
|
735 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE); |
|
736 startTitle(ol,getSourceFileBase()); |
|
737 ol.parseText(title); |
|
738 endTitle(ol,getSourceFileBase(),0); |
|
739 } |
|
740 |
|
741 if (isLinkable()) |
|
742 { |
|
743 if (latexSourceCode) ol.disable(OutputGenerator::Latex); |
|
744 ol.startTextLink(getOutputFileBase(),0); |
|
745 ol.parseText(theTranslator->trGotoDocumentation()); |
|
746 ol.endTextLink(); |
|
747 if (latexSourceCode) ol.enable(OutputGenerator::Latex); |
|
748 } |
|
749 |
|
750 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); |
|
751 pIntf->resetCodeParserState(); |
|
752 ol.startCodeFragment(); |
|
753 pIntf->parseCode(ol,0, |
|
754 fileToString(absFilePath(),filterSourceFiles), |
|
755 FALSE,0,this |
|
756 ); |
|
757 ol.endCodeFragment(); |
|
758 endFile(ol); |
|
759 ol.enableAll(); |
|
760 } |
|
761 |
|
762 void FileDef::parseSource() |
|
763 { |
|
764 static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); |
|
765 DevNullCodeDocInterface devNullIntf; |
|
766 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); |
|
767 pIntf->resetCodeParserState(); |
|
768 pIntf->parseCode( |
|
769 devNullIntf,0, |
|
770 fileToString(absFilePath(),filterSourceFiles), |
|
771 FALSE,0,this |
|
772 ); |
|
773 } |
|
774 |
|
775 void FileDef::addMembersToMemberGroup() |
|
776 { |
|
777 QListIterator<MemberList> mli(m_memberLists); |
|
778 MemberList *ml; |
|
779 for (mli.toFirst();(ml=mli.current());++mli) |
|
780 { |
|
781 if (ml->listType()&MemberList::declarationLists) |
|
782 { |
|
783 ::addMembersToMemberGroup(ml,&memberGroupSDict,this); |
|
784 } |
|
785 } |
|
786 |
|
787 // add members inside sections to their groups |
|
788 if (memberGroupSDict) |
|
789 { |
|
790 MemberGroupSDict::Iterator mgli(*memberGroupSDict); |
|
791 MemberGroup *mg; |
|
792 for (;(mg=mgli.current());++mgli) |
|
793 { |
|
794 if (mg->allMembersInSameSection() && m_subGrouping) |
|
795 { |
|
796 //printf("----> addToDeclarationSection(%s)\n",mg->header().data()); |
|
797 mg->addToDeclarationSection(); |
|
798 } |
|
799 } |
|
800 } |
|
801 } |
|
802 |
|
803 /*! Adds member definition \a md to the list of all members of this file */ |
|
804 void FileDef::insertMember(MemberDef *md) |
|
805 { |
|
806 if (md->isHidden()) return; |
|
807 //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n", |
|
808 // name().data(),md->name().data(),md,allMemberList.count()); |
|
809 MemberList *allMemberList = getMemberList(MemberList::allMembersList); |
|
810 if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef! |
|
811 { |
|
812 return; |
|
813 } |
|
814 |
|
815 if (allMemberList==0) |
|
816 { |
|
817 allMemberList = new MemberList(MemberList::allMembersList);; |
|
818 m_memberLists.append(allMemberList); |
|
819 } |
|
820 allMemberList->append(md); |
|
821 //::addFileMemberNameToIndex(md); |
|
822 switch (md->memberType()) |
|
823 { |
|
824 case MemberDef::Variable: |
|
825 case MemberDef::Property: |
|
826 addMemberToList(MemberList::decVarMembers,md); |
|
827 addMemberToList(MemberList::docVarMembers,md); |
|
828 break; |
|
829 case MemberDef::Function: |
|
830 addMemberToList(MemberList::decFuncMembers,md); |
|
831 addMemberToList(MemberList::docFuncMembers,md); |
|
832 break; |
|
833 case MemberDef::Typedef: |
|
834 addMemberToList(MemberList::decTypedefMembers,md); |
|
835 addMemberToList(MemberList::docTypedefMembers,md); |
|
836 break; |
|
837 case MemberDef::Enumeration: |
|
838 addMemberToList(MemberList::decEnumMembers,md); |
|
839 addMemberToList(MemberList::docEnumMembers,md); |
|
840 break; |
|
841 case MemberDef::EnumValue: // enum values are shown inside their enums |
|
842 break; |
|
843 case MemberDef::Define: |
|
844 addMemberToList(MemberList::decDefineMembers,md); |
|
845 addMemberToList(MemberList::docDefineMembers,md); |
|
846 break; |
|
847 default: |
|
848 err("FileDef::insertMembers(): " |
|
849 "member `%s' with class scope `%s' inserted in file scope `%s'!\n", |
|
850 md->name().data(), |
|
851 md->getClassDef() ? md->getClassDef()->name().data() : "<global>", |
|
852 name().data()); |
|
853 } |
|
854 //addMemberToGroup(md,groupId); |
|
855 } |
|
856 |
|
857 /*! Adds compound definition \a cd to the list of all compounds of this file */ |
|
858 void FileDef::insertClass(ClassDef *cd) |
|
859 { |
|
860 if (cd->isHidden()) return; |
|
861 if (classSDict==0) |
|
862 { |
|
863 classSDict = new ClassSDict(17); |
|
864 } |
|
865 if (Config_getBool("SORT_BRIEF_DOCS")) |
|
866 classSDict->inSort(cd->name(),cd); |
|
867 else |
|
868 classSDict->append(cd->name(),cd); |
|
869 } |
|
870 |
|
871 /*! Adds namespace definition \a nd to the list of all compounds of this file */ |
|
872 void FileDef::insertNamespace(NamespaceDef *nd) |
|
873 { |
|
874 if (nd->isHidden()) return; |
|
875 if (!nd->name().isEmpty() && |
|
876 (namespaceSDict==0 || namespaceSDict->find(nd->name())==0)) |
|
877 { |
|
878 if (namespaceSDict==0) |
|
879 { |
|
880 namespaceSDict = new NamespaceSDict; |
|
881 } |
|
882 if (Config_getBool("SORT_BRIEF_DOCS")) |
|
883 namespaceSDict->inSort(nd->name(),nd); |
|
884 else |
|
885 namespaceSDict->append(nd->name(),nd); |
|
886 } |
|
887 } |
|
888 |
|
889 void FileDef::addSourceRef(int line,Definition *d,MemberDef *md) |
|
890 { |
|
891 //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md); |
|
892 if (d) |
|
893 { |
|
894 if (srcDefDict==0) srcDefDict = new QIntDict<Definition>(257); |
|
895 if (srcMemberDict==0) srcMemberDict = new QIntDict<MemberDef>(257); |
|
896 srcDefDict->insert(line,d); |
|
897 if (md) srcMemberDict->insert(line,md); |
|
898 //printf("Adding member %s with anchor %s at line %d to file %s\n", |
|
899 // md->name().data(),md->anchor().data(),line,name().data()); |
|
900 } |
|
901 } |
|
902 |
|
903 Definition *FileDef::getSourceDefinition(int lineNr) |
|
904 { |
|
905 Definition *result=0; |
|
906 if (srcDefDict) |
|
907 { |
|
908 result = srcDefDict->find(lineNr); |
|
909 } |
|
910 return result; |
|
911 } |
|
912 |
|
913 MemberDef *FileDef::getSourceMember(int lineNr) |
|
914 { |
|
915 MemberDef *result=0; |
|
916 if (srcMemberDict) |
|
917 { |
|
918 result = srcMemberDict->find(lineNr); |
|
919 } |
|
920 return result; |
|
921 } |
|
922 |
|
923 |
|
924 void FileDef::addUsingDirective(NamespaceDef *nd) |
|
925 { |
|
926 if (usingDirList==0) |
|
927 { |
|
928 usingDirList = new NamespaceSDict; |
|
929 } |
|
930 if (usingDirList->find(nd->qualifiedName())==0) |
|
931 { |
|
932 usingDirList->append(nd->qualifiedName(),nd); |
|
933 } |
|
934 //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); |
|
935 } |
|
936 |
|
937 NamespaceSDict *FileDef::getUsedNamespaces() const |
|
938 { |
|
939 //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); |
|
940 return usingDirList; |
|
941 } |
|
942 |
|
943 void FileDef::addUsingDeclaration(Definition *d) |
|
944 { |
|
945 if (usingDeclList==0) |
|
946 { |
|
947 usingDeclList = new SDict<Definition>(17); |
|
948 } |
|
949 if (usingDeclList->find(d->qualifiedName())==0) |
|
950 { |
|
951 usingDeclList->append(d->qualifiedName(),d); |
|
952 } |
|
953 } |
|
954 |
|
955 void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local, |
|
956 bool imported) |
|
957 { |
|
958 //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local); |
|
959 QCString iName = fd ? fd->absFilePath().data() : incName; |
|
960 if (!iName.isEmpty() && (!includeDict || includeDict->find(iName)==0)) |
|
961 { |
|
962 if (includeDict==0) |
|
963 { |
|
964 includeDict = new QDict<IncludeInfo>(61); |
|
965 includeList = new QList<IncludeInfo>; |
|
966 includeList->setAutoDelete(TRUE); |
|
967 } |
|
968 IncludeInfo *ii = new IncludeInfo; |
|
969 ii->fileDef = fd; |
|
970 ii->includeName = incName; |
|
971 ii->local = local; |
|
972 ii->imported = imported; |
|
973 includeList->append(ii); |
|
974 includeDict->insert(iName,ii); |
|
975 } |
|
976 } |
|
977 |
|
978 void FileDef::addIncludedUsingDirectives() |
|
979 { |
|
980 if (visited) return; |
|
981 visited=TRUE; |
|
982 //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data()); |
|
983 |
|
984 NamespaceList nl; |
|
985 if (includeList) // file contains #includes |
|
986 { |
|
987 { |
|
988 QListIterator<IncludeInfo> iii(*includeList); |
|
989 IncludeInfo *ii; |
|
990 for (iii.toFirst();(ii=iii.current());++iii) // foreach #include... |
|
991 { |
|
992 if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file |
|
993 { |
|
994 // recurse into this file |
|
995 ii->fileDef->addIncludedUsingDirectives(); |
|
996 } |
|
997 } |
|
998 } |
|
999 { |
|
1000 QListIterator<IncludeInfo> iii(*includeList); |
|
1001 IncludeInfo *ii; |
|
1002 // iterate through list from last to first |
|
1003 for (iii.toLast();(ii=iii.current());--iii) |
|
1004 { |
|
1005 if (ii->fileDef && ii->fileDef!=this) |
|
1006 { |
|
1007 // add using directives |
|
1008 NamespaceSDict *unl = ii->fileDef->usingDirList; |
|
1009 if (unl) |
|
1010 { |
|
1011 NamespaceSDict::Iterator nli(*unl); |
|
1012 NamespaceDef *nd; |
|
1013 for (nli.toLast();(nd=nli.current());--nli) |
|
1014 { |
|
1015 // append each using directive found in a #include file |
|
1016 if (usingDirList==0) usingDirList = new NamespaceSDict; |
|
1017 //printf("Prepending used namespace %s to the list of file %s\n", |
|
1018 // nd->name().data(),name().data()); |
|
1019 if (usingDirList->find(nd->qualifiedName())==0) // not yet added |
|
1020 { |
|
1021 usingDirList->prepend(nd->qualifiedName(),nd); |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 // add using declarations |
|
1026 SDict<Definition> *udl = ii->fileDef->usingDeclList; |
|
1027 if (udl) |
|
1028 { |
|
1029 SDict<Definition>::Iterator udi(*udl); |
|
1030 Definition *d; |
|
1031 for (udi.toLast();(d=udi.current());--udi) |
|
1032 { |
|
1033 //printf("Adding using declaration %s\n",d->name().data()); |
|
1034 if (usingDeclList==0) |
|
1035 { |
|
1036 usingDeclList = new SDict<Definition>(17); |
|
1037 } |
|
1038 if (usingDeclList->find(d->qualifiedName())==0) |
|
1039 { |
|
1040 usingDeclList->prepend(d->qualifiedName(),d); |
|
1041 } |
|
1042 } |
|
1043 } |
|
1044 } |
|
1045 } |
|
1046 } |
|
1047 } |
|
1048 //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data()); |
|
1049 } |
|
1050 |
|
1051 |
|
1052 void FileDef::addIncludedByDependency(FileDef *fd,const char *incName, |
|
1053 bool local,bool imported) |
|
1054 { |
|
1055 //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local); |
|
1056 QCString iName = fd ? fd->absFilePath().data() : incName; |
|
1057 if (!iName.isEmpty() && (includedByDict==0 || includedByDict->find(iName)==0)) |
|
1058 { |
|
1059 if (includedByDict==0) |
|
1060 { |
|
1061 includedByDict = new QDict<IncludeInfo>(61); |
|
1062 includedByList = new QList<IncludeInfo>; |
|
1063 includedByList->setAutoDelete(TRUE); |
|
1064 } |
|
1065 IncludeInfo *ii = new IncludeInfo; |
|
1066 ii->fileDef = fd; |
|
1067 ii->includeName = incName; |
|
1068 ii->local = local; |
|
1069 ii->imported = imported; |
|
1070 includedByList->append(ii); |
|
1071 includedByDict->insert(iName,ii); |
|
1072 } |
|
1073 } |
|
1074 |
|
1075 bool FileDef::isIncluded(const QCString &name) const |
|
1076 { |
|
1077 if (name.isEmpty()) return FALSE; |
|
1078 return includeDict!=0 && includeDict->find(name)!=0; |
|
1079 } |
|
1080 |
|
1081 bool FileDef::generateSourceFile() const |
|
1082 { |
|
1083 QCString extension = name().right(4); |
|
1084 return !isReference() && |
|
1085 (Config_getBool("SOURCE_BROWSER") || |
|
1086 (Config_getBool("VERBATIM_HEADERS") && guessSection(name())==Entry::HEADER_SEC) |
|
1087 ) && |
|
1088 extension!=".doc" && extension!=".txt" && extension!=".dox"; |
|
1089 } |
|
1090 |
|
1091 |
|
1092 void FileDef::addListReferences() |
|
1093 { |
|
1094 { |
|
1095 LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); |
|
1096 addRefItem(xrefItems.pointer(), |
|
1097 getOutputFileBase(), |
|
1098 theTranslator->trFile(TRUE,TRUE), |
|
1099 getOutputFileBase(),name(), |
|
1100 0 |
|
1101 ); |
|
1102 } |
|
1103 if (memberGroupSDict) |
|
1104 { |
|
1105 MemberGroupSDict::Iterator mgli(*memberGroupSDict); |
|
1106 MemberGroup *mg; |
|
1107 for (;(mg=mgli.current());++mgli) |
|
1108 { |
|
1109 mg->addListReferences(this); |
|
1110 } |
|
1111 } |
|
1112 QListIterator<MemberList> mli(m_memberLists); |
|
1113 MemberList *ml; |
|
1114 for (mli.toFirst();(ml=mli.current());++mli) |
|
1115 { |
|
1116 if (ml->listType()&MemberList::documentationLists) |
|
1117 { |
|
1118 ml->addListReferences(this); |
|
1119 } |
|
1120 } |
|
1121 } |
|
1122 |
|
1123 //------------------------------------------------------------------- |
|
1124 |
|
1125 static int findMatchingPart(const QCString &path,const QCString dir) |
|
1126 { |
|
1127 int si1; |
|
1128 int pos1=0,pos2=0; |
|
1129 while ((si1=path.find('/',pos1))!=-1) |
|
1130 { |
|
1131 int si2=dir.find('/',pos2); |
|
1132 //printf(" found slash at pos %d in path %d: %s<->%s\n",si1,si2, |
|
1133 // path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data()); |
|
1134 if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end |
|
1135 { |
|
1136 return dir.length(); |
|
1137 } |
|
1138 if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle |
|
1139 { |
|
1140 return QMAX(pos1-1,0); |
|
1141 } |
|
1142 pos1=si1+1; |
|
1143 pos2=si2+1; |
|
1144 } |
|
1145 return 0; |
|
1146 } |
|
1147 |
|
1148 static Directory *findDirNode(Directory *root,const QCString &name) |
|
1149 { |
|
1150 QListIterator<DirEntry> dli(root->children()); |
|
1151 DirEntry *de; |
|
1152 for (dli.toFirst();(de=dli.current());++dli) |
|
1153 { |
|
1154 if (de->kind()==DirEntry::Dir) |
|
1155 { |
|
1156 Directory *dir = (Directory *)de; |
|
1157 QCString dirName=dir->name(); |
|
1158 int sp=findMatchingPart(name,dirName); |
|
1159 //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp); |
|
1160 if (sp>0) // match found |
|
1161 { |
|
1162 if ((uint)sp==dirName.length()) // whole directory matches |
|
1163 { |
|
1164 // recurse into the directory |
|
1165 return findDirNode(dir,name.mid(dirName.length()+1)); |
|
1166 } |
|
1167 else // partial match => we need to split the path into three parts |
|
1168 { |
|
1169 QCString baseName =dirName.left(sp); |
|
1170 QCString oldBranchName=dirName.mid(sp+1); |
|
1171 QCString newBranchName=name.mid(sp+1); |
|
1172 // strip file name from path |
|
1173 int newIndex=newBranchName.findRev('/'); |
|
1174 if (newIndex>0) newBranchName=newBranchName.left(newIndex); |
|
1175 |
|
1176 //printf("Splitting off part in new branch \n" |
|
1177 // "base=%s old=%s new=%s\n", |
|
1178 // baseName.data(), |
|
1179 // oldBranchName.data(), |
|
1180 // newBranchName.data() |
|
1181 // ); |
|
1182 Directory *base = new Directory(root,baseName); |
|
1183 Directory *newBranch = new Directory(base,newBranchName); |
|
1184 dir->reParent(base); |
|
1185 dir->rename(oldBranchName); |
|
1186 base->addChild(dir); |
|
1187 base->addChild(newBranch); |
|
1188 dir->setLast(FALSE); |
|
1189 // remove DirEntry container from list (without deleting it) |
|
1190 root->children().setAutoDelete(FALSE); |
|
1191 root->children().removeRef(dir); |
|
1192 root->children().setAutoDelete(TRUE); |
|
1193 // add new branch to the root |
|
1194 if (!root->children().isEmpty()) |
|
1195 { |
|
1196 root->children().last()->setLast(FALSE); |
|
1197 } |
|
1198 root->addChild(base); |
|
1199 return newBranch; |
|
1200 } |
|
1201 } |
|
1202 } |
|
1203 } |
|
1204 int si=name.findRev('/'); |
|
1205 if (si==-1) // no subdir |
|
1206 { |
|
1207 return root; // put the file under the root node. |
|
1208 } |
|
1209 else // need to create a subdir |
|
1210 { |
|
1211 QCString baseName = name.left(si); |
|
1212 //printf("new subdir %s\n",baseName.data()); |
|
1213 Directory *newBranch = new Directory(root,baseName); |
|
1214 if (!root->children().isEmpty()) |
|
1215 { |
|
1216 root->children().last()->setLast(FALSE); |
|
1217 } |
|
1218 root->addChild(newBranch); |
|
1219 return newBranch; |
|
1220 } |
|
1221 } |
|
1222 |
|
1223 static void mergeFileDef(Directory *root,FileDef *fd) |
|
1224 { |
|
1225 QCString rootPath = root->name(); |
|
1226 QCString filePath = fd->absFilePath(); |
|
1227 //printf("merging %s\n",filePath.data()); |
|
1228 Directory *dirNode = findDirNode(root,filePath); |
|
1229 if (!dirNode->children().isEmpty()) |
|
1230 { |
|
1231 dirNode->children().last()->setLast(FALSE); |
|
1232 } |
|
1233 DirEntry *e=new DirEntry(dirNode,fd); |
|
1234 dirNode->addChild(e); |
|
1235 } |
|
1236 |
|
1237 #if 0 |
|
1238 static void generateIndent(QTextStream &t,DirEntry *de,int level) |
|
1239 { |
|
1240 if (de->parent()) |
|
1241 { |
|
1242 generateIndent(t,de->parent(),level+1); |
|
1243 } |
|
1244 // from the root up to node n do... |
|
1245 if (level==0) // item before a dir or document |
|
1246 { |
|
1247 if (de->isLast()) |
|
1248 { |
|
1249 if (de->kind()==DirEntry::Dir) |
|
1250 { |
|
1251 t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>"; |
|
1252 } |
|
1253 else |
|
1254 { |
|
1255 t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>"; |
|
1256 } |
|
1257 } |
|
1258 else |
|
1259 { |
|
1260 if (de->kind()==DirEntry::Dir) |
|
1261 { |
|
1262 t << "<img " << FTV_IMGATTRIBS(pnode) << "/>"; |
|
1263 } |
|
1264 else |
|
1265 { |
|
1266 t << "<img " << FTV_IMGATTRIBS(node) << "/>"; |
|
1267 } |
|
1268 } |
|
1269 } |
|
1270 else // item at another level |
|
1271 { |
|
1272 if (de->isLast()) |
|
1273 { |
|
1274 t << "<img " << FTV_IMGATTRIBS(blank) << "/>"; |
|
1275 } |
|
1276 else |
|
1277 { |
|
1278 t << "<img " << FTV_IMGATTRIBS(vertline) << "/>"; |
|
1279 } |
|
1280 } |
|
1281 } |
|
1282 |
|
1283 static void writeDirTreeNode(QTextStream &t,Directory *root,int level) |
|
1284 { |
|
1285 QCString indent; |
|
1286 indent.fill(' ',level*2); |
|
1287 QListIterator<DirEntry> dli(root->children()); |
|
1288 DirEntry *de; |
|
1289 for (dli.toFirst();(de=dli.current());++dli) |
|
1290 { |
|
1291 t << indent << "<p>"; |
|
1292 generateIndent(t,de,0); |
|
1293 if (de->kind()==DirEntry::Dir) |
|
1294 { |
|
1295 Directory *dir=(Directory *)de; |
|
1296 //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir); |
|
1297 t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>"; |
|
1298 t << dir->name(); |
|
1299 t << "</p>\n"; |
|
1300 t << indent << "<div>\n"; |
|
1301 writeDirTreeNode(t,dir,level+1); |
|
1302 t << indent << "</div>\n"; |
|
1303 } |
|
1304 else |
|
1305 { |
|
1306 //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir); |
|
1307 t << "<img " << FTV_IMGATTRIBS(doc) << "/>"; |
|
1308 t << de->file()->name(); |
|
1309 t << "</p>\n"; |
|
1310 } |
|
1311 } |
|
1312 } |
|
1313 #endif |
|
1314 |
|
1315 static void addDirsAsGroups(Directory *root,GroupDef *parent,int level) |
|
1316 { |
|
1317 GroupDef *gd=0; |
|
1318 if (root->kind()==DirEntry::Dir) |
|
1319 { |
|
1320 gd = new GroupDef("[generated]", |
|
1321 1, |
|
1322 root->path(), // name |
|
1323 root->name() // title |
|
1324 ); |
|
1325 if (parent) |
|
1326 { |
|
1327 parent->addGroup(gd); |
|
1328 gd->makePartOfGroup(parent); |
|
1329 } |
|
1330 else |
|
1331 { |
|
1332 Doxygen::groupSDict->append(root->path(),gd); |
|
1333 } |
|
1334 } |
|
1335 QListIterator<DirEntry> dli(root->children()); |
|
1336 DirEntry *de; |
|
1337 for (dli.toFirst();(de=dli.current());++dli) |
|
1338 { |
|
1339 if (de->kind()==DirEntry::Dir) |
|
1340 { |
|
1341 addDirsAsGroups((Directory *)de,gd,level+1); |
|
1342 } |
|
1343 } |
|
1344 } |
|
1345 |
|
1346 void generateFileTree() |
|
1347 { |
|
1348 Directory *root=new Directory(0,"root"); |
|
1349 root->setLast(TRUE); |
|
1350 FileNameListIterator fnli(*Doxygen::inputNameList); |
|
1351 FileName *fn; |
|
1352 for (fnli.toFirst();(fn=fnli.current());++fnli) |
|
1353 { |
|
1354 FileNameIterator fni(*fn); |
|
1355 FileDef *fd; |
|
1356 for (;(fd=fni.current());++fni) |
|
1357 { |
|
1358 mergeFileDef(root,fd); |
|
1359 } |
|
1360 } |
|
1361 //t << "<div class=\"directory\">\n"; |
|
1362 //writeDirTreeNode(t,root,0); |
|
1363 //t << "</div>\n"; |
|
1364 addDirsAsGroups(root,0,0); |
|
1365 delete root; |
|
1366 } |
|
1367 |
|
1368 //------------------------------------------------------------------- |
|
1369 |
|
1370 void FileDef::combineUsingRelations() |
|
1371 { |
|
1372 if (visited) return; // already done |
|
1373 visited=TRUE; |
|
1374 if (usingDirList) |
|
1375 { |
|
1376 NamespaceSDict::Iterator nli(*usingDirList); |
|
1377 NamespaceDef *nd; |
|
1378 for (nli.toFirst();(nd=nli.current());++nli) |
|
1379 { |
|
1380 nd->combineUsingRelations(); |
|
1381 } |
|
1382 for (nli.toFirst();(nd=nli.current());++nli) |
|
1383 { |
|
1384 // add used namespaces of namespace nd to this namespace |
|
1385 if (nd->getUsedNamespaces()) |
|
1386 { |
|
1387 NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); |
|
1388 NamespaceDef *und; |
|
1389 for (unli.toFirst();(und=unli.current());++unli) |
|
1390 { |
|
1391 //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); |
|
1392 addUsingDirective(und); |
|
1393 } |
|
1394 } |
|
1395 // add used classes of namespace nd to this namespace |
|
1396 if (nd->getUsedClasses()) |
|
1397 { |
|
1398 SDict<Definition>::Iterator cli(*nd->getUsedClasses()); |
|
1399 Definition *ucd; |
|
1400 for (cli.toFirst();(ucd=cli.current());++cli) |
|
1401 { |
|
1402 //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); |
|
1403 addUsingDeclaration(ucd); |
|
1404 } |
|
1405 } |
|
1406 } |
|
1407 } |
|
1408 } |
|
1409 |
|
1410 bool FileDef::isDocumentationFile() const |
|
1411 { |
|
1412 return name().right(4)==".doc" || |
|
1413 name().right(4)==".txt" || |
|
1414 name().right(4)==".dox"; |
|
1415 } |
|
1416 |
|
1417 void FileDef::acquireFileVersion() |
|
1418 { |
|
1419 QCString vercmd = Config_getString("FILE_VERSION_FILTER"); |
|
1420 if (!vercmd.isEmpty()) |
|
1421 { |
|
1422 msg("Version of %s : ",filepath.data()); |
|
1423 QCString cmd = vercmd+" \""+filepath+"\""; |
|
1424 Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data()); |
|
1425 FILE *f=portable_popen(cmd,"r"); |
|
1426 if (!f) |
|
1427 { |
|
1428 err("Error: could not execute %s\n",vercmd.data()); |
|
1429 return; |
|
1430 } |
|
1431 const int bufSize=1024; |
|
1432 char buf[bufSize]; |
|
1433 int numRead = fread(buf,1,bufSize,f); |
|
1434 portable_pclose(f); |
|
1435 if (numRead > 0) |
|
1436 { |
|
1437 fileVersion = QCString(buf,numRead).stripWhiteSpace(); |
|
1438 msg("%s\n",fileVersion.data()); |
|
1439 } |
|
1440 else |
|
1441 { |
|
1442 msg("no version available\n"); |
|
1443 } |
|
1444 } |
|
1445 } |
|
1446 |
|
1447 |
|
1448 QCString FileDef::getSourceFileBase() const |
|
1449 { |
|
1450 if (Htags::useHtags) |
|
1451 { |
|
1452 return Htags::path2URL(filepath); |
|
1453 } |
|
1454 else |
|
1455 { |
|
1456 return convertNameToFile(diskname)+"_source"; |
|
1457 } |
|
1458 } |
|
1459 |
|
1460 /*! Returns the name of the verbatim copy of this file (if any). */ |
|
1461 QCString FileDef::includeName() const |
|
1462 { |
|
1463 if (Htags::useHtags) |
|
1464 { |
|
1465 return Htags::path2URL(filepath); |
|
1466 } |
|
1467 else |
|
1468 { |
|
1469 return convertNameToFile(diskname)+"_source"; |
|
1470 } |
|
1471 } |
|
1472 |
|
1473 MemberList *FileDef::createMemberList(MemberList::ListType lt) |
|
1474 { |
|
1475 m_memberLists.setAutoDelete(TRUE); |
|
1476 QListIterator<MemberList> mli(m_memberLists); |
|
1477 MemberList *ml; |
|
1478 for (mli.toFirst();(ml=mli.current());++mli) |
|
1479 { |
|
1480 if (ml->listType()==lt) |
|
1481 { |
|
1482 return ml; |
|
1483 } |
|
1484 } |
|
1485 // not found, create a new member list |
|
1486 ml = new MemberList(lt); |
|
1487 m_memberLists.append(ml); |
|
1488 return ml; |
|
1489 } |
|
1490 |
|
1491 void FileDef::addMemberToList(MemberList::ListType lt,MemberDef *md) |
|
1492 { |
|
1493 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); |
|
1494 static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS"); |
|
1495 MemberList *ml = createMemberList(lt); |
|
1496 if (((ml->listType()&MemberList::declarationLists) && sortBriefDocs) || |
|
1497 ((ml->listType()&MemberList::documentationLists) && sortMemberDocs) |
|
1498 ) |
|
1499 ml->inSort(md); |
|
1500 else |
|
1501 ml->append(md); |
|
1502 if (lt&MemberList::documentationLists) |
|
1503 { |
|
1504 ml->setInFile(TRUE); |
|
1505 } |
|
1506 if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml); |
|
1507 } |
|
1508 |
|
1509 MemberList *FileDef::getMemberList(MemberList::ListType lt) const |
|
1510 { |
|
1511 FileDef *that = (FileDef*)this; |
|
1512 MemberList *ml = that->m_memberLists.first(); |
|
1513 while (ml) |
|
1514 { |
|
1515 if (ml->listType()==lt) |
|
1516 { |
|
1517 return ml; |
|
1518 } |
|
1519 ml = that->m_memberLists.next(); |
|
1520 } |
|
1521 return 0; |
|
1522 } |
|
1523 |
|
1524 void FileDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title) |
|
1525 { |
|
1526 static bool optVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); |
|
1527 MemberList * ml = getMemberList(lt); |
|
1528 if (ml) |
|
1529 { |
|
1530 if (optVhdl) // use specific declarations function |
|
1531 { |
|
1532 VhdlDocGen::writeVhdlDeclarations(ml,ol,0,0,this); |
|
1533 } |
|
1534 else |
|
1535 { |
|
1536 ml->writeDeclarations(ol,0,0,this,0,title,0); |
|
1537 } |
|
1538 } |
|
1539 } |
|
1540 |
|
1541 void FileDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title) |
|
1542 { |
|
1543 MemberList * ml = getMemberList(lt); |
|
1544 if (ml) ml->writeDocumentation(ol,name(),this,title); |
|
1545 } |
|
1546 |
|
1547 bool FileDef::isLinkableInProject() const |
|
1548 { |
|
1549 static bool showFiles = Config_getBool("SHOW_FILES"); |
|
1550 return hasDocumentation() && !isReference() && showFiles; |
|
1551 } |
|
1552 |