diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 1999-12-15 19:34:06 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 1999-12-15 19:34:06 (GMT) |
commit | ee8333a5d2ecf84deeb5d05ed8b23c212729cdac (patch) | |
tree | 43e0b215b5d3d2b436509cbb1cd22102aef61b1d /src | |
parent | 6aa7383e23c850af36c25b87e5737a2e2f635083 (diff) | |
download | Doxygen-ee8333a5d2ecf84deeb5d05ed8b23c212729cdac.zip Doxygen-ee8333a5d2ecf84deeb5d05ed8b23c212729cdac.tar.gz Doxygen-ee8333a5d2ecf84deeb5d05ed8b23c212729cdac.tar.bz2 |
mods for doxygen-0.49-990829
Diffstat (limited to 'src')
62 files changed, 4446 insertions, 1906 deletions
diff --git a/src/Makefile b/src/Makefile.in index 9812d37..66ff412 100644 --- a/src/Makefile +++ b/src/Makefile.in @@ -1,3 +1,4 @@ + # # $Id$ # @@ -12,8 +13,6 @@ # All output generated with Doxygen is not covered by this license. # -include ../Makefile.config - all: Makefile.doxygen Makefile.doxytag Makefile.doxysearch Makefile $(MAKE) -f Makefile.doxygen $@ $(MAKE) -f Makefile.doxytag $@ @@ -37,7 +36,7 @@ clean: $(MAKE) -f Makefile.doxygen clean $(MAKE) -f Makefile.doxytag clean $(MAKE) -f Makefile.doxysearch clean - -rm -f scanner.cpp code.cpp config.cpp pre.cpp ce_lex.cpp \ + -$(RM) scanner.cpp code.cpp config.cpp pre.cpp ce_lex.cpp \ ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp \ declinfo.cpp defargs.cpp diff --git a/src/classdef.cpp b/src/classdef.cpp index 005a397..5d7c980 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -28,6 +28,7 @@ #include "util.h" #include "diagram.h" #include "language.h" +#include "htmlhelp.h" static QCString stripExtension(const char *fName) { @@ -66,7 +67,7 @@ ClassDef::ClassDef(const char *nm,CompoundType ct,const char *ref,const char *fN allMemberNameInfoList->setAutoDelete(TRUE); allMemberNameInfoDict = new MemberNameInfoDict(1009); visited=FALSE; - reference=ref; + setReference(ref); compType=ct; incFile=0; tempArgs=0; @@ -103,7 +104,7 @@ void ClassDef::insertSuperClass(ClassDef *cd,Protection p, void ClassDef::insertMember(const MemberDef *md) { //printf("adding %s::%s\n",name(),md->name()); - if (!reference) + if (!isReference()) { if (md->isRelated() && (Config::extractPrivateFlag || md->protection()!=Private)) { @@ -224,10 +225,10 @@ void ClassDef::writeDocumentation(OutputList &ol) QCString pageType; switch(compType) { - case Class: pageType=" Class"; break; - case Struct: pageType=" Struct"; break; - case Union: pageType=" Union"; break; - default: pageType+=compType; break; // an error + case Class: pageType=" Class"; break; + case Struct: pageType=" Struct"; break; + case Union: pageType=" Union"; break; + default: pageType=" Interface"; break; } pageTitle+=pageType+" Reference"; startFile(ol,fileName,pageTitle); @@ -302,7 +303,7 @@ void ClassDef::writeDocumentation(OutputList &ol) if (ok && bcd) { ClassDef *cd=bcd->classDef; - if (cd->hasDocumentation() || cd->isReference()) + if (cd->isLinkable()) { if (Config::genTagFile.length()>0) tagFile << cd->getOutputFileBase() << "?"; ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->name()+bcd->templSpecifiers); @@ -340,7 +341,7 @@ void ClassDef::writeDocumentation(OutputList &ol) if (ok && bcd) { ClassDef *cd=bcd->classDef; - if (cd->hasDocumentation() || cd->isReference()) + if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->name()); } @@ -364,14 +365,14 @@ void ClassDef::writeDocumentation(OutputList &ol) while (ibcd) { ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleExt()) count++; + if ( icd->isVisibleInHierarchy()) count++; ibcd=inheritedBy->next(); } ibcd=inherits->first(); while (ibcd) { ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleExt()) count++; + if ( icd->isVisibleInHierarchy()) count++; ibcd=inherits->next(); } if (Config::classDiagramFlag && count>0) @@ -386,7 +387,7 @@ void ClassDef::writeDocumentation(OutputList &ol) } // write link to list of all members (HTML only) - if (allMemberNameInfoList->count()>0 && compType==Class) + if (allMemberNameInfoList->count()>0 /*&& compType==Class*/) { ol.disableAllBut(OutputGenerator::Html); ol.startTextLink(memListFileName,0); @@ -397,24 +398,23 @@ void ClassDef::writeDocumentation(OutputList &ol) // write member groups ol.startMemberSections(); - writeMemberDecs(ol,this,0,0,theTranslator->trPublicMembers(),0,&pubMembers); - writeMemberDecs(ol,this,0,0,theTranslator->trPublicSlots(),0,&pubSlots); - writeMemberDecs(ol,this,0,0,theTranslator->trSignals(),0,&signals); - writeMemberDecs(ol,this,0,0,theTranslator->trStaticPublicMembers(),0,&pubStaticMembers); - writeMemberDecs(ol,this,0,0,theTranslator->trProtectedMembers(),0,&proMembers); - writeMemberDecs(ol,this,0,0,theTranslator->trProtectedSlots(),0,&proSlots); - writeMemberDecs(ol,this,0,0,theTranslator->trStaticProtectedMembers(),0,&proStaticMembers); + pubMembers.writeDeclarations(ol,this,0,0,theTranslator->trPublicMembers(),0); + pubSlots.writeDeclarations(ol,this,0,0,theTranslator->trPublicSlots(),0); + signals.writeDeclarations(ol,this,0,0,theTranslator->trSignals(),0); + pubStaticMembers.writeDeclarations(ol,this,0,0,theTranslator->trStaticPublicMembers(),0); + proMembers.writeDeclarations(ol,this,0,0,theTranslator->trProtectedMembers(),0); + proSlots.writeDeclarations(ol,this,0,0,theTranslator->trProtectedSlots(),0); + proStaticMembers.writeDeclarations(ol,this,0,0,theTranslator->trStaticProtectedMembers(),0); if (Config::extractPrivateFlag) { - writeMemberDecs(ol,this,0,0,theTranslator->trPrivateMembers(),0,&priMembers); - writeMemberDecs(ol,this,0,0,theTranslator->trPrivateSlots(),0,&priSlots); - writeMemberDecs(ol,this,0,0,theTranslator->trStaticPrivateMembers(),0,&priStaticMembers); + priMembers.writeDeclarations(ol,this,0,0,theTranslator->trPrivateMembers(),0); + priSlots.writeDeclarations(ol,this,0,0,theTranslator->trPrivateSlots(),0); + priStaticMembers.writeDeclarations(ol,this,0,0,theTranslator->trStaticPrivateMembers(),0); } - writeMemberDecs(ol,this,0,0,theTranslator->trFriends(),0,&friends); - writeMemberDecs(ol,this,0,0, + friends.writeDeclarations(ol,this,0,0,theTranslator->trFriends(),0); + related.writeDeclarations(ol,this,0,0, theTranslator->trRelatedFunctions(), - theTranslator->trRelatedSubscript(), - &related + theTranslator->trRelatedSubscript() ); ol.endMemberSections(); @@ -519,11 +519,11 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,theTranslator->trMemberTypedefDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,&pubMembers,name(),MemberDef::Typedef); - writeMemberDocs(ol,&proMembers,name(),MemberDef::Typedef); + pubMembers.writeDocumentation(ol,name(),MemberDef::Typedef); + proMembers.writeDocumentation(ol,name(),MemberDef::Typedef); if (Config::extractPrivateFlag) { - writeMemberDocs(ol,&priMembers,name(),MemberDef::Typedef); + priMembers.writeDocumentation(ol,name(),MemberDef::Typedef); } } @@ -537,11 +537,11 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,theTranslator->trMemberEnumerationDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,&pubMembers,name(),MemberDef::Enumeration); - writeMemberDocs(ol,&proMembers,name(),MemberDef::Enumeration); + pubMembers.writeDocumentation(ol,name(),MemberDef::Enumeration); + proMembers.writeDocumentation(ol,name(),MemberDef::Enumeration); if (Config::extractPrivateFlag) { - writeMemberDocs(ol,&priMembers,name(),MemberDef::Enumeration); + priMembers.writeDocumentation(ol,name(),MemberDef::Enumeration); } } @@ -555,41 +555,48 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,theTranslator->trEnumerationValueDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,&pubMembers,name(),MemberDef::EnumValue); - writeMemberDocs(ol,&proMembers,name(),MemberDef::EnumValue); + pubMembers.writeDocumentation(ol,name(),MemberDef::EnumValue); + proMembers.writeDocumentation(ol,name(),MemberDef::EnumValue); if (Config::extractPrivateFlag) { - writeMemberDocs(ol,&priMembers,name(),MemberDef::EnumValue); + priMembers.writeDocumentation(ol,name(),MemberDef::EnumValue); } } - if ( pubMembers.funcCount() + pubSlots.funcCount() + + int func_count=0; + if ( + ( + func_count = + pubMembers.funcCount() + pubSlots.funcCount() + pubStaticMembers.funcCount() + proMembers.funcCount() + proSlots.funcCount() + proStaticMembers.funcCount() + (Config::extractPrivateFlag ? priMembers.funcCount() + priSlots.funcCount() + priStaticMembers.funcCount() : 0 - ) + ) + ) ) { ol.writeRuler(); ol.startGroupHeader(); - parseText(ol,theTranslator->trMemberFunctionDocumentation()); + QCString countStr; + //countStr.sprintf(" (%d)",func_count); + parseText(ol,theTranslator->trMemberFunctionDocumentation()+countStr); ol.endGroupHeader(); - writeMemberDocs(ol,&pubMembers,name(),MemberDef::Function); - writeMemberDocs(ol,&pubSlots,name(),MemberDef::Slot); - writeMemberDocs(ol,&signals,name(),MemberDef::Signal); - writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Function); - writeMemberDocs(ol,&proMembers,name(),MemberDef::Function); - writeMemberDocs(ol,&proSlots,name(),MemberDef::Slot); - writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Function); + pubMembers.writeDocumentation(ol,name(),MemberDef::Function); + pubSlots.writeDocumentation(ol,name(),MemberDef::Slot); + signals.writeDocumentation(ol,name(),MemberDef::Signal); + pubStaticMembers.writeDocumentation(ol,name(),MemberDef::Function); + proMembers.writeDocumentation(ol,name(),MemberDef::Function); + proSlots.writeDocumentation(ol,name(),MemberDef::Slot); + proStaticMembers.writeDocumentation(ol,name(),MemberDef::Function); if (Config::extractPrivateFlag) { - writeMemberDocs(ol,&priMembers,name(),MemberDef::Function); - writeMemberDocs(ol,&priSlots,name(),MemberDef::Slot); - writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Function); + priMembers.writeDocumentation(ol,name(),MemberDef::Function); + priSlots.writeDocumentation(ol,name(),MemberDef::Slot); + priStaticMembers.writeDocumentation(ol,name(),MemberDef::Function); } } @@ -599,8 +606,8 @@ void ClassDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trRelatedFunctionDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,&friends,name(),MemberDef::Friend); - writeMemberDocs(ol,&related,name(),MemberDef::Function); + friends.writeDocumentation(ol,name(),MemberDef::Friend); + related.writeDocumentation(ol,name(),MemberDef::Function); } @@ -616,22 +623,21 @@ void ClassDef::writeDocumentation(OutputList &ol) parseText(ol,theTranslator->trMemberDataDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,&pubMembers,name(),MemberDef::Variable); - writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Variable); - writeMemberDocs(ol,&proMembers,name(),MemberDef::Variable); - writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Variable); + pubMembers.writeDocumentation(ol,name(),MemberDef::Variable); + pubStaticMembers.writeDocumentation(ol,name(),MemberDef::Variable); + proMembers.writeDocumentation(ol,name(),MemberDef::Variable); + proStaticMembers.writeDocumentation(ol,name(),MemberDef::Variable); if (Config::extractPrivateFlag) { - writeMemberDocs(ol,&priMembers,name(),MemberDef::Variable); - writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Variable); + priMembers.writeDocumentation(ol,name(),MemberDef::Variable); + priStaticMembers.writeDocumentation(ol,name(),MemberDef::Variable); } } // write the list of used files (Html and LaTeX only) ol.disable(OutputGenerator::Man); ol.writeRuler(); - parseText(ol,theTranslator->trGeneratedFrom(pageType.lower(), - files.count()==1)); + parseText(ol,theTranslator->trGeneratedFromFiles(compType,files.count()==1)); bool first=TRUE; const char *file = files.first(); @@ -651,15 +657,10 @@ void ClassDef::writeDocumentation(OutputList &ol) QCString path=fd->getPath().copy(); if (Config::fullPathNameFlag) { - // strip part of the path - if (path.left(Config::stripFromPath.length())==Config::stripFromPath) - { - path=path.right(path.length()-Config::stripFromPath.length()); - } - ol.docify(path); + ol.docify(stripFromPath(path)); } - if (fd->hasDocumentation()) + if (fd->isLinkable()) { ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0, fd->name()); @@ -697,7 +698,7 @@ void ClassDef::writeMemberList(OutputList &ol) parseText(ol,name()+" "+theTranslator->trMemberList()); endTitle(ol,0); parseText(ol,theTranslator->trThisIsTheListOfAllMembers()); - ol.writeObjectLink(reference,fileName,0,name()); + ol.writeObjectLink(getReference(),fileName,0,name()); parseText(ol,theTranslator->trIncludingInheritedMembers()); ol.startItemList(); @@ -738,7 +739,7 @@ void ClassDef::writeMemberList(OutputList &ol) ) { bool memberWritten=FALSE; - if (cd->isVisible() && (md->hasDocumentation() || md->isReference())) + if (cd->isLinkable() && md->isLinkable()) // create a link to the documentation { QCString name=mi->ambiguityResolutionScope+md->name(); @@ -773,7 +774,7 @@ void ClassDef::writeMemberList(OutputList &ol) ol.docify(" typedef"); ol.writeString(" ("); parseText(ol,theTranslator->trDefinedIn()+" "); - if (cd->isVisible()) + if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->name()); } @@ -927,33 +928,33 @@ void ClassDef::setTemplateArguments(ArgumentList *al) } } -QCString ClassDef::getTemplateNameString() -{ - QCString result; - if (!tempArgs || tempArgs->count()==0) return result; - result="<"; - Argument *a=tempArgs->first(); - while (a) - { - if (a->name.length()>0) // add template argument name - { - result+=a->name; - } - else // extract name from type - { - int i=a->type.length()-1; - while (i>=0 && isId(a->type.at(i))) i--; - if (i>0) - { - result+=a->type.right(a->type.length()-i-1); - } - } - a=tempArgs->next(); - if (a) result+=", "; - } - result+=">"; - return result; -} +//QCString ClassDef::getTemplateNameString() +//{ +// QCString result; +// if (!tempArgs || tempArgs->count()==0) return result; +// result="<"; +// Argument *a=tempArgs->first(); +// while (a) +// { +// if (a->name.length()>0) // add template argument name +// { +// result+=a->name; +// } +// else // extract name from type +// { +// int i=a->type.length()-1; +// while (i>=0 && isId(a->type.at(i))) i--; +// if (i>0) +// { +// result+=a->type.right(a->type.length()-i-1); +// } +// } +// a=tempArgs->next(); +// if (a) result+=", "; +// } +// result+=">"; +// return result; +//} bool ClassDef::hasNonReferenceSuperClass() { @@ -963,3 +964,59 @@ bool ClassDef::hasNonReferenceSuperClass() found=found || bcli.current()->classDef->hasNonReferenceSuperClass(); return found; } + +//void ClassDef::writeMembersToContents() +//{ +// HtmlHelp *htmlHelp = HtmlHelp::getInstance(); +// +// htmlHelp->incContentsDepth(); +// +// MemberNameInfoListIterator mnili(*allMemberNameInfoList); +// MemberNameInfo *mni; +// for (;(mni=mnili.current());++mnili) +// { +// MemberNameInfoIterator mnii(*mni); +// MemberInfo *mi; +// for (mnii.toLast();(mi=mnii.current());--mnii) +// { +// MemberDef *md=mi->memberDef; +// ClassDef *cd=md->memberClass(); +// if (md->isLinkable() && cd==this) // member is not inherited +// { +// htmlHelp->addContentsItem(md->name()+md->argsString(), +// cd->getOutputFileBase(), +// md->anchor()); +// } +// } +// } +// htmlHelp->decContentsDepth(); +//} + +void ClassDef::writeDeclaration(OutputList &ol) +{ + //ol.insertMemberAlign(); + switch(compType) + { + case Class: ol.docify("class {"); break; + case Struct: ol.docify("struct {"); break; + default: ol.docify("union {"); break; + } + ol.endMemberItem(FALSE,0,0,FALSE); // TODO: pass correct group parameters + + // insert members of this class + pubMembers.writePlainDeclarations(ol,this,0,0); + pubSlots.writePlainDeclarations(ol,this,0,0); + signals.writePlainDeclarations(ol,this,0,0); + pubStaticMembers.writePlainDeclarations(ol,this,0,0); + proMembers.writePlainDeclarations(ol,this,0,0); + proSlots.writePlainDeclarations(ol,this,0,0); + proStaticMembers.writePlainDeclarations(ol,this,0,0); + if (Config::extractPrivateFlag) + { + priMembers.writePlainDeclarations(ol,this,0,0); + priSlots.writePlainDeclarations(ol,this,0,0); + priStaticMembers.writePlainDeclarations(ol,this,0,0); + } + friends.writePlainDeclarations(ol,this,0,0); + related.writePlainDeclarations(ol,this,0,0); +} diff --git a/src/classdef.h b/src/classdef.h index dd24b69..ed2aa9d 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -46,7 +46,8 @@ class ClassDef : public Definition enum CompoundType { Class=Entry::CLASS_SEC, Struct=Entry::STRUCT_SEC, - Union=Entry::UNION_SEC + Union=Entry::UNION_SEC, + Interface=Entry::INTERFACE_SEC }; ClassDef(const char *name,CompoundType ct,const char *ref=0,const char *fName=0); @@ -54,7 +55,7 @@ class ClassDef : public Definition //QCString classFile() const { return fileName; } QCString getOutputFileBase() const { return fileName; } CompoundType compoundType() const { return compType; } - const char *memberListFileName() const { return memListFileName; } + //const char *memberListFileName() const { return memListFileName; } void insertBaseClass(ClassDef *,Protection p,Specifier s,const char *t=0); BaseClassList *baseClasses() { return inherits; } void insertSuperClass(ClassDef *,Protection p,Specifier s,const char *t=0); @@ -64,8 +65,8 @@ class ClassDef : public Definition void setIncludeName(const char *n_) { incName=n_; } MemberNameInfoList *memberNameInfoList() { return allMemberNameInfoList; } MemberNameInfoDict *memberNameInfoDict() { return allMemberNameInfoDict; } - bool isReference() { return !reference.isNull(); } - const char *getReference() const { return reference; } + //bool isReference() { return !reference.isNull(); } + //const char *getReference() const { return reference; } void insertMember(const MemberDef *); void insertUsedFile(const char *); void computeAnchors(); @@ -74,29 +75,45 @@ class ClassDef : public Definition void writeDocumentation(OutputList &ol); void writeMemberList(OutputList &ol); void writeIncludeFile(OutputList &ol); + //void writeMembersToContents(); + void writeDeclaration(OutputList &ol); bool addExample(const char *anchor,const char *name, const char *file); bool hasExamples(); //void writeExample(OutputList &ol); void setProtection(Protection p) { prot=p; } Protection protection() const { return prot; } - bool isVisible() - { return !name().isEmpty() && name().at(0)!='@' && - (prot!=Private || Config::extractPrivateFlag) && - hasDocumentation(); - } + /*! a link to this class is possible within this project */ + bool isLinkableInProject() + { int i = name().findRev("::"); + if (i==-1) i=0; else i+=2; + return !name().isEmpty() && name().at(i)!='@' && + (prot!=Private || Config::extractPrivateFlag) && + hasDocumentation() && !isReference(); + } + /*! a link to this class is possible (either within this project, + * or as a cross-reference to another project + */ + bool isLinkable() + { + return isLinkableInProject() || isReference(); + } bool hasNonReferenceSuperClass(); - bool isVisibleExt() - { return (Config::allExtFlag || hasNonReferenceSuperClass()) && - !name().isEmpty() && name().at(0)!='@' && - (prot!=Private || Config::extractPrivateFlag) && - (hasDocumentation() || !Config::hideClassFlag || - !reference.isNull()); - } + /*! the class is visible in a class diagram, or class hierarchy */ + bool isVisibleInHierarchy() + { return // show all classes or a superclass is visible + (Config::allExtFlag || hasNonReferenceSuperClass()) && + // and not an annonymous compound + name().find('@')==-1 && + // and not privately inherited + (prot!=Private || Config::extractPrivateFlag) && + // documented or show anyway or documentation is external + (hasDocumentation() || !Config::hideClassFlag || isReference()); + } // template argument functions ArgumentList *templateArguments() const { return tempArgs; } void setTemplateArguments(ArgumentList *al); - QCString getTemplateNameString(); + //QCString getTemplateNameString(); void setNamespace(NamespaceDef *nd) { nspace = nd; } NamespaceDef *getNamespace() { return nspace; } @@ -129,7 +146,7 @@ class ClassDef : public Definition MemberNameInfoDict *allMemberNameInfoDict; ArgumentList *tempArgs; QStrList files; - QCString reference; + //QCString reference; ExampleList *exampleList; ExampleDict *exampleDict; CompoundType compType; @@ -167,7 +167,7 @@ static void generateClassLink(OutputList &ol,const char *clName) QCString className=clName; if (className.length()==0) return; ClassDef *cd; - if ((cd=getClass(className)) && cd->isVisible()) + if ((cd=getClass(className)) && cd->isLinkable()) { if (exampleBlock) { @@ -202,8 +202,7 @@ static bool getLink(const char *className, QCString m=memberName; QCString c=className; //printf("Trying `%s'::`%s'\n",c.data(),m.data()); - if (getDefs(c,m,"()",md,cd,fd,nd) && - (md->hasDocumentation() || md->isReference())) + if (getDefs(c,m,"()",md,cd,fd,nd) && md->isLinkable()) { //printf("Found!\n"); if (exampleBlock) @@ -218,24 +217,35 @@ static bool getLink(const char *className, anchorCount++; } } - if (cd) - { - result.writeCodeLink(cd->getReference(),cd->getOutputFileBase(), - md->anchor(),memberName); - return TRUE; - } - else if (nd) - { - result.writeCodeLink(nd->getReference(),nd->getOutputFileBase(), - md->anchor(),memberName); - return TRUE; - } - else if (fd) + Definition *d=0; + if (cd) d=cd; else if (cd) d=nd; else d=fd; + + if (d) { - result.writeCodeLink(fd->getReference(),fd->getOutputFileBase(), - md->anchor(),memberName); + result.writeCodeLink(d->getReference(),d->getOutputFileBase(), + md->anchor(),memberName); return TRUE; - } + + } + +// if (cd) +// { +// result.writeCodeLink(cd->getReference(),cd->getOutputFileBase(), +// md->anchor(),memberName); +// return TRUE; +// } +// else if (nd) +// { +// result.writeCodeLink(nd->getReference(),nd->getOutputFileBase(), +// md->anchor(),memberName); +// return TRUE; +// } +// else if (fd) +// { +// result.writeCodeLink(fd->getReference(),fd->getOutputFileBase(), +// md->anchor(),memberName); +// return TRUE; +// } } return FALSE; @@ -372,7 +382,7 @@ ID [a-z_A-Z][a-z_A-Z0-9]* bool ambig; FileDef *fd; if ((fd=findFileDef(&inputNameDict,yytext,ambig)) && - fd->hasDocumentation()) + fd->isLinkable()) { code->writeCodeLink(0,fd->getOutputFileBase(),0,yytext); } diff --git a/src/config.h b/src/config.h index d2bec11..9d04582 100644 --- a/src/config.h +++ b/src/config.h @@ -49,7 +49,6 @@ struct Config static QCString genTagFile; // the tag file to generate static QCString inputFilter; // a filter command that is applied to input files static QCString paperType; // the page type to generate docs for - static QCString stripFromPath; // the string to strip from the file path static QCString manExtension; // extension the man page files static QStrList includePath; // list of include paths static QStrList examplePath; // list of example paths @@ -61,6 +60,7 @@ struct Config static QStrList extDocPathList; // list of external doc. directories. static QStrList predefined; // list of predefined macro names. static QStrList extraPackageList; // list of extra LaTeX packages. + static QStrList stripFromPath; // list of candidates to strip from the file path static bool quietFlag; // generate progress messages flag static bool warningFlag; // generate warnings flag static bool recursiveFlag; // scan directories recursively @@ -89,6 +89,8 @@ struct Config static bool htmlAlignMemberFlag; // align members in HTML using tables. static bool includeSourceFlag; // include source code in documentation. static bool autoBriefFlag; // javadoc comments behaves as Qt comments. + static bool htmlHelpFlag; // should html help files be generated? + static bool alphaIndexFlag; // should an alphabetical index be generated? }; #endif diff --git a/src/config.l b/src/config.l index 57897e9..515de4d 100644 --- a/src/config.l +++ b/src/config.l @@ -81,7 +81,6 @@ QCString Config::perlPath; QCString Config::genTagFile; QCString Config::inputFilter; QCString Config::paperType; -QCString Config::stripFromPath; QCString Config::manExtension; QStrList Config::includePath; QStrList Config::examplePath; @@ -93,6 +92,7 @@ QStrList Config::tagFileList; QStrList Config::extDocPathList; QStrList Config::predefined; QStrList Config::extraPackageList; +QStrList Config::stripFromPath; bool Config::quietFlag = FALSE; bool Config::recursiveFlag = FALSE; bool Config::allExtFlag = FALSE; @@ -109,6 +109,8 @@ bool Config::compactLatexFlag = FALSE; bool Config::internalDocsFlag = FALSE; bool Config::caseSensitiveNames = FALSE; bool Config::includeSourceFlag = FALSE; +bool Config::htmlHelpFlag = FALSE; +bool Config::alphaIndexFlag = FALSE; bool Config::autoBriefFlag = TRUE; bool Config::warningFlag = TRUE; bool Config::generateHtml = TRUE; @@ -188,7 +190,6 @@ static int yyread(char *buf,int max_size) <Start>"INPUT_FILTER"[ \t]*"=" { BEGIN(GetString); s=&Config::inputFilter; } <Start>"PAPER_TYPE"[ \t]*"=" { BEGIN(GetString); s=&Config::paperType; } <Start>"OUTPUT_LANGUAGE"[ \t]*"=" { BEGIN(GetString); s=&Config::outputLanguage; } -<Start>"STRIP_FROM_PATH"[ \t]*"=" { BEGIN(GetString); s=&Config::stripFromPath; } <Start>"MAN_EXTENSION"[ \t]*"=" { BEGIN(GetString); s=&Config::manExtension; } <Start>"INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&Config::includePath; elemStr=""; } <Start>"EXAMPLE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&Config::examplePath; elemStr=""; } @@ -200,6 +201,7 @@ static int yyread(char *buf,int max_size) <Start>"EXT_DOC_PATHS"[ \t]*"=" { BEGIN(GetStrList); l=&Config::extDocPathList; elemStr=""; } <Start>"PREDEFINED"[ \t]*"=" { BEGIN(GetStrList); l=&Config::predefined; elemStr=""; } <Start>"EXTRA_PACKAGES"[ \t]*"=" { BEGIN(GetStrList); l=&Config::extraPackageList; elemStr=""; } +<Start>"STRIP_FROM_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&Config::stripFromPath; elemStr=""; } <Start>"QUIET"[ \t]*"=" { BEGIN(GetBool); b=&Config::quietFlag; } <Start>"WARNINGS"[ \t]*"=" { BEGIN(GetBool); b=&Config::warningFlag; } <Start>"RECURSIVE"[ \t]*"=" { BEGIN(GetBool); b=&Config::recursiveFlag; } @@ -228,6 +230,8 @@ static int yyread(char *buf,int max_size) <Start>"HTML_ALIGN_MEMBERS"[ \t]*"=" { BEGIN(GetBool); b=&Config::htmlAlignMemberFlag; } <Start>"SOURCE_BROWSER"[ \t]*"=" { BEGIN(GetBool); b=&Config::includeSourceFlag; } <Start>"JAVADOC_AUTOBRIEF"[ \t]*"=" { BEGIN(GetBool); b=&Config::autoBriefFlag; } +<Start>"GENERATE_HTMLHELP"[ \t]*"=" { BEGIN(GetBool); b=&Config::htmlHelpFlag; } +<Start>"ALPHABETICAL_INDEX"[ \t]*"=" { BEGIN(GetBool); b=&Config::alphaIndexFlag; } <Start>[a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d\n",yytext,yyLineNr); } <GetString,GetBool>\n { yyLineNr++; BEGIN(Start); } <GetStrList>\n { @@ -381,7 +385,6 @@ void Config::init() Config::genTagFile.resize(0); Config::inputFilter.resize(0); Config::paperType = "a4wide"; - Config::stripFromPath.resize(0); Config::manExtension = ".3"; Config::includePath.clear(); Config::examplePath.clear(); @@ -393,6 +396,7 @@ void Config::init() Config::extDocPathList.clear(); Config::predefined.clear(); Config::extraPackageList.clear(); + Config::stripFromPath.clear(); Config::quietFlag = FALSE; Config::recursiveFlag = FALSE; Config::allExtFlag = FALSE; @@ -409,6 +413,8 @@ void Config::init() Config::internalDocsFlag = FALSE; Config::caseSensitiveNames = FALSE; Config::includeSourceFlag = FALSE; + Config::htmlHelpFlag = FALSE; + Config::alphaIndexFlag = FALSE; Config::warningFlag = TRUE; Config::generateHtml = TRUE; Config::generateLatex = TRUE; @@ -429,7 +435,7 @@ void writeTemplateConfig(QFile *f,bool sl) #ifdef DOXYWIZARD t << "# Doxygen configuration generated by Doxywizard version " << versionString << endl; #else - t << "# Doxyfile " << versionString << endl; + t << "# Doxyfile " << versionString << endl << endl; #endif if (!sl) { @@ -440,9 +446,12 @@ void writeTemplateConfig(QFile *f,bool sl) t << "# TAG = value [value, ...]\n"; t << "# Values that contain spaces should be placed between quotes (\" \")\n"; t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# General configuration options\n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# General configuration options\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# The PROJECT_NAME tag is a single word (or a sequence of word surrounded\n"; t << "# by quotes) that should identify the project. \n"; @@ -581,7 +590,8 @@ void writeTemplateConfig(QFile *f,bool sl) t << "\n"; t << "# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag\n"; t << "# can be used to strip a user defined part of the path. Stripping is\n" ; - t << "# only done if the specified string matches the left-hand part of the path.\n"; + t << "# only done if one of the specified strings matches the left-hand part of\n"; + t << "# the path.\n"; t << "\n"; } t << "STRIP_FROM_PATH =\n"; @@ -597,20 +607,20 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen\n"; - t << "# will only generate file names in lower case letters. If set to\n"; - t << "# YES upper case letters are also allowed. This is useful if you have\n"; - t << "# classes or files whose names only differ in case and if your file system\n"; - t << "# supports case sensitive file names.\n"; + t << "# If the SOURCE_BROWSER tag is set to YES than the body of a member or\n"; + t << "# function will be appended as a block of code to the documentation of.\n"; + t << "# that member or function.\n"; t << "\n"; } t << "SOURCE_BROWSER = NO\n"; if (!sl) { t << "\n"; - t << "# If the SOURCE_BROWSER tag is set to YES than the body of a member or\n"; - t << "# function will be appended as a block of code to the documentation of.\n"; - t << "# that member or function.\n"; + t << "# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen\n"; + t << "# will only generate file names in lower case letters. If set to\n"; + t << "# YES upper case letters are also allowed. This is useful if you have\n"; + t << "# classes or files whose names only differ in case and if your file system\n"; + t << "# supports case sensitive file names.\n"; t << "\n"; } t << "CASE_SENSE_NAMES = NO\n"; @@ -636,9 +646,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# configuration options related to the input files\n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# configuration options related to the input files\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# The INPUT tag can be used to specify the files and/or directories that contain \n"; t << "# documented source files. You may enter file names like \"myfile.cpp\" or \n"; @@ -708,9 +721,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# configuration options related to the HTML output\n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# configuration options related to the HTML output\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# If the GENERATE_HTML tag is set to YES (the default) Doxygen will\n"; t << "# generate HTML output\n"; @@ -756,9 +772,31 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# configuration options related to the LaTeX output\n"; - t << "#---------------------------------------------------------------------------\n"; + t << "# If the GENERATE_HTMLHELP tag is set to YES, additional index files\n"; + t << "# will be generated that can be used as input for tools like the\n"; + t << "# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)\n"; + t << "# of the generated HTML documentation.\n"; + t << "\n"; + } + t << "GENERATE_HTMLHELP = NO\n"; + if (!sl) + { + t << "\n"; + t << "# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index\n"; + t << "# of all compounds will be generated. Enable this if the project\n"; + t << "# contains a lot of classes, structs, unions or interfaces.\n"; + t << "\n"; + } + t << "ALPHABETICAL_INDEX = NO\n"; + if (!sl) + { + t << "\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# configuration options related to the LaTeX output\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will\n"; t << "# generate Latex output.\n"; @@ -803,9 +841,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# configuration options related to the man page output\n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# configuration options related to the man page output\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# If the GENERATE_MAN tag is set to YES (the default) Doxygen will\n"; t << "# generate man pages\n"; @@ -833,9 +874,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# Configuration options related to the preprocessor \n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# Configuration options related to the preprocessor \n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will\n"; t << "# evaluate all C-preprocessor directives found in the sources and include\n"; @@ -892,9 +936,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# Configuration options related to external references \n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# Configuration options related to external references \n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# The TAGFILES tag can be used to specify one or more tagfiles. \n"; t << "\n"; @@ -928,9 +975,12 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; - t << "#---------------------------------------------------------------------------\n"; - t << "# Configuration options related to the search engine \n"; - t << "#---------------------------------------------------------------------------\n"; + } + t << "#---------------------------------------------------------------------------\n"; + t << "# Configuration options related to the search engine \n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { t << "\n"; t << "# The SEARCHENGINE tag specifies whether or not a search engine should be \n"; t << "# used. If set to NO the values of all tags below this one will be ignored.\n"; diff --git a/src/declinfo.l b/src/declinfo.l index dfa3e47..3737a67 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -223,15 +223,17 @@ void parseFuncDecl(const QCString &decl,QCString &cl,QCString &ctl,QCString &t, declinfoYYlex(); cl=scope.copy(); + //printf("scope=`%s'\n",scope.data()); int il,ir; if ((il=cl.find('<'))!=-1 && (ir=cl.findRev('>'))!=-1) // split up scope and template arguments { - if (ir==-1) ir=cl.length(); else ir++; - ctl=removeRedundantWhiteSpace(cl.mid(il,ir-il)); - cl=cl.left(il)+cl.right(cl.length()-ir); + ctl=removeRedundantWhiteSpace(cl.mid(il,ir-il+1)); + cl=cl.left(il)+cl.right(cl.length()-ir-1); } + //printf("cl=`%s' ctl=`%s'\n",cl.data(),ctl.data()); n=removeRedundantWhiteSpace(name); - if ((il=n.find('<'))!=-1 && n.left(8)!="operator") + if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1) + // TODO: handle cases like where n="operator<< <T>" { ftl=removeRedundantWhiteSpace(n.right(n.length()-il)); n=n.left(il); diff --git a/src/defargs.l b/src/defargs.l index d82c2fe..f214404 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -45,6 +45,7 @@ static QCString *copyArgValue; static QCString curArgTypeName; static QCString curArgDefValue; static QCString curArgName; +static QCString curArgAttrib; static int argRoundCount; static int argSharpCount; static int argCurlyCount; @@ -94,6 +95,12 @@ ID [a-z_A-Z][a-z_A-Z0-9]* <ReadFuncArgType>{B}* { curArgTypeName+=" "; } +<ReadFuncArgType>"["[^\]]*"]" { + if (curArgTypeName.stripWhiteSpace().isEmpty()) + curArgAttrib=yytext; + else + curArgTypeName+=yytext; + } <ReadFuncArgDef>"'"\\[0-7]{1,3}"'" { curArgDefValue+=yytext; } <ReadFuncArgDef>"'"\\."'" { curArgDefValue+=yytext; } <ReadFuncArgDef>"'"."'" { curArgDefValue+=yytext; } @@ -216,6 +223,7 @@ ID [a-z_A-Z][a-z_A-Z0-9]* ) ) i--; Argument *a = new Argument; + a->attrib = curArgAttrib.copy(); if (i>=0 && curArgTypeName.at(i)!=':') { // type contains a name a->type = curArgTypeName.left(i+1).stripWhiteSpace(); @@ -229,6 +237,7 @@ ID [a-z_A-Z][a-z_A-Z0-9]* //printf("----> Adding argument `%s' `%s' `%s'\n",a->type.data(),a->name.data(),a->defval.data()); argList->append(a); } + curArgAttrib.resize(0); curArgTypeName.resize(0); curArgDefValue.resize(0); if (*yytext==')') diff --git a/src/define.cpp b/src/define.cpp index 336d6da..343ac00 100644 --- a/src/define.cpp +++ b/src/define.cpp @@ -21,6 +21,8 @@ Define::Define() { undef=FALSE; fileDef=0; + isPredefined=FALSE; + nonRecursive=FALSE; } Define::Define(const Define &d) diff --git a/src/define.h b/src/define.h index 92027af..8577b55 100644 --- a/src/define.h +++ b/src/define.h @@ -42,6 +42,8 @@ class Define int nargs; bool undef; bool varArgs; + bool isPredefined; + bool nonRecursive; }; class DefineList : public QList<Define> diff --git a/src/definition.h b/src/definition.h index 282ecdc..40e8316 100644 --- a/src/definition.h +++ b/src/definition.h @@ -26,44 +26,72 @@ class Definition { public: - //! create a new definition + /*! create a new definition */ Definition(const char *name,const char *b=0,const char *d=0); - //! destroys the definition + /*! destroys the definition */ virtual ~Definition(); - //! returns the name of the definition + /*! returns the name of the definition */ QCString name() const { return n; } - //! returns the base name of the output file that contains this definition. + /*! returns the base name of the output file that contains this + * definition. + */ virtual QCString getOutputFileBase() const = 0; - //! returns the detailed description of this definition + /*! returns the detailed description of this definition */ QCString documentation() const { return doc; } - //! returns the brief description of this definition + /*! returns the brief description of this definition */ QCString briefDescription() const { return brief; } - //! sets a new name for the definition + /*! sets a new \a name for the definition */ void setName(const char *name) { n=name; } - //! sets the documentation of this definition + /*! sets the documentation of this definition to \a d. */ void setDocumentation(const char *d) { - doc=d; doc=doc.stripWhiteSpace(); + doc=((QCString)d).stripWhiteSpace(); } - //! sets the brief description of this definition + /*! sets the brief description of this definition to \a b. + * A dot is added to the sentence if not available. + */ void setBriefDescription(const char *b) { - brief=b; brief=brief.stripWhiteSpace(); + brief=((QCString) b).stripWhiteSpace(); int bl=brief.length(); - if (bl>0 && brief.at(bl-1)!='.' && brief.at(bl-1)!='!' && - brief.at(bl-1)!='?') brief+='.'; + if (bl>0) // add puntuation if needed + { + switch(brief.at(bl-1)) + { + case '.': case '!': case '?': break; + default: brief+='.'; break; + } + } } - //! returns TRUE iff the definition is documented + /*! returns TRUE iff the definition is documented */ virtual bool hasDocumentation() { return !doc.isNull() || !brief.isNull() || Config::extractAllFlag; } + + virtual bool isLinkableInProject() = 0; + virtual bool isLinkable() = 0; + + bool isReference() { return !ref.isEmpty(); } + void setReference(const char *r) { ref=r; } + QCString getReference() { return ref; } + + /*! returns the base file name that corresponds with the \a name of this + * definition. This replaces a number of special characters in the + * name by string that are more suitable to use in file names. + * The function getOutputFileBase() also uses this function in most cases. + * \sa setName(),Definition() + */ QCString nameToFile(const char *name); + /*! Add the list of anchors that mark the sections that are found in the + * documentation. + */ void addSectionsToDefinition(QList<QCString> *anchorList); private: QCString n; // name of the definition QCString brief; // brief description QCString doc; // detailed description + QCString ref; // reference to external documentation SectionList *sectionList; // list of all sections }; diff --git a/src/diagram.cpp b/src/diagram.cpp index 8cbe128..d25b334 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -148,7 +148,7 @@ static void writeVectorBox(QTextStream &t,DiagramItem *di, static void writeMapArea(QTextStream &t,ClassDef *cd,int x,int y,int w,int h) { - if (cd->hasDocumentation() || cd->isReference()) + if (cd->isLinkable()) { t << "<area "; if (cd->getReference()) t << "doxygen=\"" << cd->getReference() << ":\" "; @@ -229,10 +229,7 @@ void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases, while (bcd) { ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleExt() - //(ccd->protection()!=Private || extractPrivateFlag) && - //(ccd->hasDocumentation() || !hideClassFlag) - ) count++; + if (ccd && ccd->isVisibleInHierarchy()) count++; bcd=bcl->next(); } if (count>0 && (prot!=Private || !doBases)) @@ -252,10 +249,7 @@ void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases, while (bcd) { ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleExt() - //(ccd->protection()!=Private || extractPrivateFlag) && - //(ccd->hasDocumentation() || !hideClassFlag) - ) + if (ccd && ccd->isVisibleInHierarchy()) { row->insertClass(di,ccd,doBases,bcd->prot, doBases?bcd->virt:Normal, @@ -519,8 +513,7 @@ void TreeDiagram::drawBoxes(QTextStream &t,Image *image, if (bitmap) { - bool hasDocs=di->getClassDef()->hasDocumentation() || - di->getClassDef()->isReference(); + bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow, hasDocs,di->getChildren()->count()>0); if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight); @@ -553,8 +546,7 @@ void TreeDiagram::drawBoxes(QTextStream &t,Image *image, y = (baseRows-1)*(cellHeight+labelVertSpacing)+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; } - bool hasDocs=di->getClassDef()->hasDocumentation() || - di->getClassDef()->isReference(); + bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight); } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 76518ba..01ac9b6 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -47,6 +47,8 @@ #include "mangen.h" #include "language.h" #include "debug.h" +#include "htmlhelp.h" +#include "defargs.h" #if defined(_MSC_VER) #define popen _popen @@ -60,7 +62,6 @@ PageList exampleList; // list of all example files PageList pageList; // list of all related documentation pages MemberNameList memberNameList; // list of class member + related functions MemberNameList functionNameList; // list of all unrelated functions -//MemberNameList namespaceNameList; // list of namespace members; FileNameList inputNameList; // list of all input files StringList inputFiles; FileList includeFiles; @@ -74,7 +75,6 @@ ClassDict classDict(1009); // dictionary of all documented classes NamespaceDict namespaceDict(257); // dictionary of all documented namespaces MemberNameDict memberNameDict(10007); // dictionary of all class member names MemberNameDict functionNameDict(10007); // dictionary of all functions -//MemberNameDict namespaceNameDict(10007);// dictionaty of all namespace member names StringDict substituteDict(1009); // dictionary of class name substitutes SectionDict sectionDict(257); // dictionary of all page sections FileNameDict inputNameDict(1009); // dictionary of sections @@ -87,6 +87,7 @@ StringDict typedefDict(1009); // dictionary of all typedefs GroupDict groupDict(257); // dictionary of all groups FormulaDict formulaDict(1009); // dictionary of all formulas FormulaDict formulaNameDict(1009); // dictionary of the label name of all formulas + // a member group OutputList *outputList; // list of output generating objects @@ -103,6 +104,7 @@ int documentedFiles; int documentedGroups; int documentedNamespaces; int documentedNamespaceMembers; +int documentedIncludeFiles; QTextStream tagFile; @@ -260,6 +262,7 @@ void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root) bool ambig; FileDef *fd=0; // see if we need to include a verbatim copy of the header file + //printf("root->includeFile=%s\n",root->includeFile.data()); if (!root->includeFile.isNull() && (fd=findFileDef(&inputNameDict,root->includeFile,ambig))==0 ) @@ -280,9 +283,9 @@ void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root) else // name is not an input file warn("is not an input file\n"); } - else if (root->includeFile.length()==0 && + else if (root->includeFile.isEmpty() && ifd && // see if the file extension makes sense - guessSection(root->includeFile)==Entry::HEADER_SEC) + guessSection(ifd->name())==Entry::HEADER_SEC) { // implicit assumption fd=ifd; } @@ -296,7 +299,8 @@ void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root) cd->setIncludeFile(fd); // set include supplied name cd->setIncludeName(root->includeName); - fd->setIncludeName(cd->getOutputFileBase()+"-include"); + if (cd->name().find('@')==-1) + fd->setIncludeName(cd->getOutputFileBase()+"-include"); if (includeDict[fd->absFilePath()]==0) // include not inserted earlier { includeFiles.inSort(fd); @@ -317,6 +321,8 @@ void extractNamespaceName(const QCString &scopeName, { // the whole name is a namespace namespaceName=clName.copy(); className.resize(0); + //printf("extractNamespace `%s' => `%s|%s'\n",scopeName.data(), + // className.data(),namespaceName.data()); return; } int i,p=clName.length()-2; @@ -327,12 +333,16 @@ void extractNamespaceName(const QCString &scopeName, { namespaceName=clName.left(i); className=clName.right(clName.length()-i-2); + //printf("extractNamespace `%s' => `%s|%s'\n",scopeName.data(), + // className.data(),namespaceName.data()); return; } p=i-2; // try a smaller piece of the scope } className=scopeName.copy(); namespaceName.resize(0); + //printf("extractNamespace `%s' => `%s|%s'\n",scopeName.data(), + // className.data(),namespaceName.data()); return; } @@ -384,6 +394,7 @@ void buildClassList(Entry *root) else { fullName=stripAnnonymousScope(fullName); + //printf("new class with name %s\n",fullName.data()); bool ambig; ClassDef *cd; @@ -391,7 +402,7 @@ void buildClassList(Entry *root) { if (cd->templateArguments()==0) { - //printf("existing ClassDef tempArgList=%p\n",root->tArgList); + //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data()); cd->setTemplateArguments(root->tArgList); } if (root->doc.length()>0 || root->brief.length()>0) // block contains docs @@ -430,10 +441,14 @@ void buildClassList(Entry *root) case Entry::STRUCT_SEC: case Entry::STRUCTDOC_SEC: sec=ClassDef::Struct; break; + case Entry::INTERFACE_SEC: + case Entry::INTERFACEDOC_SEC: + sec=ClassDef::Interface; break; } ClassDef *cd=new ClassDef(fullName,sec); cd->setDocumentation(root->doc); // copy docs to definition cd->setBriefDescription(root->brief); + //printf("new ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data()); cd->setTemplateArguments(root->tArgList); cd->setProtection(root->protection); cd->addSectionsToDefinition(root->anchors); @@ -531,6 +546,12 @@ void buildNamespaceList(Entry *root) fullName.data(),root->fileName.data(),root->startLine); } } + + bool ambig; + // file definition containing the namespace nd + FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); + // insert the namespace in the file definition + if (fd) fd->insertNamespace(nd); } else /* if (root->doc.length()>0 || root->brief.length()>0 || @@ -553,7 +574,7 @@ void buildNamespaceList(Entry *root) } bool ambig; - // file definition containing the class cd + // file definition containing the namespace nd FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig); // insert the namespace in the file definition if (fd) fd->insertNamespace(nd); @@ -575,6 +596,98 @@ void buildNamespaceList(Entry *root) } } +static MemberDef *addVariableToClass(Entry *root,ClassDef *cd, + MemberDef::MemberType mtype,const QCString &scope,const QCString &name, + bool fromAnnScope,int indentDepth,MemberDef *fromAnnMemb) +{ + Debug::print(Debug::Variables,0, + " class variable:\n" + " %s' %s'::`%s' `%s' prot=`%d\n", + root->type.data(), + scope.data(), + name.data(), + root->args.data(), + root->protection + ); + // add template names, if the class is a non-specialized template + //if (scope.find('<')==-1 && cd->templateArguments()) + //{ + // scope+=cd->getTemplateNameString(); + //} + // generate member definition. + QCString def; + if (root->type.length()>0) + { + if (mtype==MemberDef::Friend) + { + def=root->type+" "+name+root->args; + } + else + { + def=root->type+" "+scope+"::"+name+root->args; + } + } + else + { + def=scope+"::"+name+root->args; + } + if (def.left(7)=="static ") def=def.right(def.length()-7); + + // see if the member is already found in the same scope + // (this may be the case for a static member that is initialized + // outside the class) + MemberName *mn=memberNameDict[name]; + if (mn) + { + MemberDef *md=mn->first(); + while (md) + { + if (md->memberClass()==cd) // member already in the scope + { + addMemberDocs(root,md,def,FALSE); + return md; + } + md=mn->next(); + } + } + // new member variable, typedef or enum value + MemberDef *md=new MemberDef(root->type,name,root->args,0, + root->protection,Normal,root->stat,FALSE, + mtype,0,0); + md->setMemberClass(cd); + md->setDefFile(root->fileName); + md->setDefLine(root->startLine); + md->setDocumentation(root->doc); + md->setBriefDescription(root->brief); + md->setDefinition(def); + md->addSectionsToDefinition(root->anchors); + md->setFromAnnonymousScope(fromAnnScope); + md->setFromAnnonymousMember(fromAnnMemb); + md->setIndentDepth(indentDepth); + + // add the member to the global list + if (mn) + { + //printf("Member already found! %s\n",md->name()); + //addMemberDocs(root,mn->first(),def,FALSE); + //delete md; + mn->inSort(md); + } + else // new variable name + { + mn = new MemberName(name); + mn->inSort(md); + //printf("Adding memberName=%s\n",mn->memberName()); + memberNameDict.insert(name,mn); + memberNameList.inSort(mn); + // add the member to the class + } + cd->insertMember(md); + + //TODO: insert FileDef instead of filename strings. + cd->insertUsedFile(root->fileName); + return md; +} //---------------------------------------------------------------------- // Searches the Entry tree for Variable documentation sections. @@ -611,7 +724,7 @@ void buildVarList(Entry *root) // recover from parse error caused by redundant braces root->type=root->name; QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*"); - int i,l; + int l; i=re.match(root->args,0,&l); root->name=root->args.mid(i,l); root->args=root->args.mid(i+l, @@ -621,7 +734,7 @@ void buildVarList(Entry *root) } else { - QRegExp re("([^)]*)"); + //QRegExp re("([^)]*)"); i=root->type.find(re,0); if (i!=-1) // function variable { @@ -631,7 +744,10 @@ void buildVarList(Entry *root) } QCString scope,name=root->name.copy(); - bool stat=root->stat; + //bool stat=root->stat; + + // find the scope of this variable (stripping the annonymous part + // at the beginning Entry *p = root->parent; while ((p->section & Entry::SCOPE_MASK)) { @@ -641,16 +757,17 @@ void buildVarList(Entry *root) scope.prepend(scopeName); break; } - //if (p->name.length()>0 && p->name[0]!='@') - //{ - // if (!scope.isEmpty()) scope.prepend("::"); - // scope.prepend(p->name); - // break; - //} p=p->parent; } - - //printf("scope=%s\n",scope.data()); + // scope annonymous scope name at the end to determine the scope + // where we can put this variable + + //while ((i=scope.findRev("::"))!=-1 && (int)scope.length()>i+2 && + // scope.at(i+2)=='@' + // ) + //{ + // scope=scope.left(i); + //} int ni; if ((ni=root->name.findRev("::"))!=-1) goto nextMember; @@ -676,94 +793,28 @@ void buildVarList(Entry *root) ClassDef *cd=0; if (scope.length()>0 && name.length()>0 && (cd=getClass(scope))) { - - Debug::print(Debug::Variables,0, - " class variable:\n" - " %s' %s'::`%s' `%s' prot=`%d\n", - root->type.data(), - scope.data(), - name.data(), - root->args.data(), - root->protection - ); - // add template names, if the class is a non-specialized template - //if (scope.find('<')==-1 && cd->templateArguments()) - //{ - // scope+=cd->getTemplateNameString(); - //} - // generate member definition. - QCString def; - if (root->type.length()>0) - { - if (mtype==MemberDef::Friend) - { - def=root->type+" "+name+root->args; - } - else - { - def=root->type+" "+scope+"::"+name+root->args; - } - } - else - { - def=scope+"::"+name+root->args; - } - if (def.left(7)=="static ") def=def.right(def.length()-7); - - // see if the member is already found in the same scope - // (this may be the case for a static member that is initialized - // outside the class) - bool found=FALSE; - MemberName *mn=memberNameDict[name]; - if (mn) - { - MemberDef *md=mn->first(); - while (md && !found) - { - if (md->memberClass()==cd) // member already in the scope - { - addMemberDocs(root,md,def,FALSE); - found=TRUE; - } - md=mn->next(); - } - } - if (!found) // found a fresh variable + MemberDef *md=0; + // if cd is an annonymous scope we insert the member + // into a non-annonymous scope as well. + int indentDepth=0; + if (scope.find('@')!=-1) { - // new member variable, typedef or enum value - MemberDef *md=new MemberDef(root->type,name,root->args,0, - root->protection,Normal,stat,FALSE, - mtype,0,0); - md->setMemberClass(cd); - md->setDefFile(root->fileName); - md->setDefLine(root->startLine); - md->setDocumentation(root->doc); - md->setBriefDescription(root->brief); - md->setDefinition(def); - md->addSectionsToDefinition(root->anchors); - - // add the member to the global list - if (mn) + QCString pScope = scope.copy(); + ClassDef *pcd=0; + while ((i=pScope.findRev("::"))!=-1 && (int)pScope.length()>i+2 && + pScope.at(i+2)=='@' + ) { - //printf("Member already found! %s\n",md->name()); - //addMemberDocs(root,mn->first(),def,FALSE); - //delete md; - mn->inSort(md); + pScope=pScope.left(i); + indentDepth++; } - else // new variable name + if ((pcd=getClass(pScope))) { - mn = new MemberName(name); - mn->inSort(md); - //printf("Adding memberName=%s\n",mn->memberName()); - memberNameDict.insert(name,mn); - memberNameList.inSort(mn); - // add the member to the class + //printf("Inserting member in parent scope!\n"); + md=addVariableToClass(root,pcd,mtype,pScope,name,TRUE,indentDepth,0); } - cd->insertMember(md); - - //TODO: insert FileDef instead of filename strings. - cd->insertUsedFile(root->fileName); - } + } + addVariableToClass(root,cd,mtype,scope,name,FALSE,indentDepth,md); } else if (name.length()>0) // global variable { @@ -874,7 +925,7 @@ void buildMemberList(Entry *root) { Debug::print(Debug::Functions,0, "FUNCTION_SEC:\n" - " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' #targs=%d docs=`%s'\n", + " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' #targs=%d #mtargs=%d mGrpId=%d\n", root->type.data(), root->parent->name.data(), root->name.data(), @@ -882,7 +933,8 @@ void buildMemberList(Entry *root) root->relates.data(), root->fileName.data(), root->tArgList ? (int)root->tArgList->count() : -1, - root->doc.data() + root->mtArgList ? (int)root->mtArgList->count() : -1, + root->mGrpId ); bool isFriend=root->type.find("friend ")!=-1; @@ -924,6 +976,13 @@ void buildMemberList(Entry *root) else if (root->slot) mtype=MemberDef::Slot; else mtype=MemberDef::Function; + // strip redundant template specifier for constructors + if ((i=name.find('<'))!=-1 && name.find('>')!=-1) + { + name=name.left(i); + } + + //if (Config::includeSourceFlag && !root->body.isEmpty()) //{ // printf("Function: %s\n-----------------\n%s\n------------------\n", @@ -935,14 +994,15 @@ void buildMemberList(Entry *root) // root->args.data(),argListToString(cd->templateArguments()).data()); MemberDef *md=new MemberDef(root->type,name,root->args,root->exception, root->protection,root->virt,root->stat,root->relates.length()>0, - mtype,root->tArgList,root->argList); + mtype,root->mtArgList,root->argList); md->setMemberClass(cd); md->setDefFile(root->fileName); md->setDefLine(root->startLine); md->setDocumentation(root->doc); md->setBriefDescription(root->brief); md->setBody(root->body); - //md->setScopeTemplateArguments(cd->templateArguments()); + md->setGroupId(root->mGrpId); + //md->setScopeTemplateArguments(root->tArgList); md->addSectionsToDefinition(root->anchors); QCString def; if (root->relates.length()>0 || isFriend) @@ -1090,6 +1150,7 @@ void buildMemberList(Entry *root) md->setPrototype(root->proto); md->setBody(root->body); md->addSectionsToDefinition(root->anchors); + md->setGroupId(root->mGrpId); QCString def; if (root->type.length()>0) { @@ -1323,14 +1384,14 @@ void computeClassRelations(Entry *root) // For nested classes the base class could also be nested! // To find the correct scope, we try to prepend the scope to the base // name, starting with the largest, most inner scope. - while (p->section&Entry::COMPOUND_MASK && !found) + while (p->section&Entry::SCOPE_MASK && !found) { scopePrefix=p->name+"::"; QList<BaseInfo> *baseList=root->extends; BaseInfo *bi=baseList->first(); while (bi && !found) // for each base class { - QCString cName=scopePrefix+bi->name; + QCString cName=removeRedundantWhiteSpace(scopePrefix+bi->name); //printf("Base class %s\n",cName.data()); ClassDef *baseClass=getClass(cName); if (baseClass) // base class is documented @@ -1358,21 +1419,22 @@ void computeClassRelations(Entry *root) BaseInfo *bi=baseList->first(); while (bi) // for each base class { - ClassDef *baseClass=getClass(bi->name); + QCString baseClassName=removeRedundantWhiteSpace(bi->name); + ClassDef *baseClass=getClass(baseClassName); //printf("baseClass %s of %s found (%s and %s)\n", - // bi->name.data(), + // baseClassName.data(), // root->name.data(), // (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"), // (bi->virt==Normal)?"normal":"virtual" // ); int i; - QCString templSpec,baseClassName=bi->name.copy(); - if (!baseClass && (i=bi->name.find('<'))!=-1) + QCString templSpec; + if (!baseClass && (i=baseClassName.find('<'))!=-1) // base class has template specifiers { // TODO: here we should try to find the correct template specialization // but for now, we only look for the unspecializated base class. - baseClassName=bi->name.left(i); + baseClassName=baseClassName.left(i); baseClass=getClass(baseClassName); templSpec=bi->name.right(bi->name.length()-i); } @@ -1415,27 +1477,8 @@ void computeClassRelations(Entry *root) } bi=baseList->next(); } - } - } -// else // class has no base classes -// { -// QCString resName=resolveDefines(root->name); -// int i; -// // Check if this class is a template instance of another class. -// // If this is the case, we act as if this class `inherits' from the -// // template class. -// if ((i=resName.find('<'))!=-1) -// { -// ClassDef *baseClass=getClass(resName.left(i)); -// if (baseClass) -// { -// // add base class to this class -// cd->insertBaseClass(baseClass,Public,Normal); -// // add this class as super class to the base class -// baseClass->insertSuperClass(cd,Public,Normal); -// } -// } -// } + } // class not nested + } // class has no base classes } // else class is already found } else if (root->name.right(2)!="::") @@ -1564,6 +1607,22 @@ void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl, md->setDefLine(root->startLine); md->addSectionsToDefinition(root->anchors); if (cd) cd->insertUsedFile(root->fileName); + if (root->mGrpId!=-1) + { + if (md->groupId()!=-1) + { + if (md->groupId()!=root->mGrpId) + { + warn("Warning: member %s belongs to two different group. The second " + "one is found at line %d of %s and will be ignored\n", + md->name().data(),root->startLine,root->fileName.data()); + } + } + else // copy group id + { + md->setGroupId(root->mGrpId); + } + } } //---------------------------------------------------------------------- @@ -1656,7 +1715,7 @@ void substituteTemplateArgNames(ArgumentList *src, while ((i=re.match(s,p,&l))!=-1) // for each template name found at the // member definition { - Argument *ta = tempArgs->at(c); + Argument *ta = c<(int)tempArgs->count() ? tempArgs->at(c) : 0; if (ta) // get matching template argument of the class { QCString dstName=s.mid(i,l); @@ -1724,6 +1783,31 @@ void substituteTemplateArgNames(ArgumentList *src, } +QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &templ) +{ + QCString result=scope.copy(); + if (!templ.isEmpty() && scope.find('<')==-1) + { + int si,pi=0; + while ((si=scope.find("::",pi))!=-1 && !getClass(scope.left(si)+templ) + && !getClass(scope.left(si))) + { //printf("Tried `%s'\n",(scope.left(si)+templ).data()); + pi=si+2; + } + if (si==-1) // not nested => append template specifier + { + result+=templ; + } + else // nested => insert template specifier before after first class name + { + result=scope.left(si) + templ + scope.right(scope.length()-si); + } + } + //printf("insertTemplateSpecifierInScope(`%s',`%s')=%s\n", + // scope.data(),templ.data(),result.data()); + return result; +} + //---------------------------------------------------------------------- // This function tries to find a member (in a documented class/file/namespace) // that corresponds to the function declaration given in `funcDecl'. @@ -1739,8 +1823,10 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, bool isFunc) { Debug::print(Debug::FindMembers,0, - "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,isFunc=%d\n====\ndoc=%s\n====\n)\n", - root,funcDecl.data(),related.data(),overloaded,isFunc,root->doc.data() + "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,isFunc=%d mGrpId=%d tArgList=%p=\"%s\" scopeSpec=%s memberSpec=%s\n", + root,funcDecl.data(),related.data(),overloaded,isFunc,root->mGrpId, + root->tArgList,tempArgListToString(root->tArgList).data(), + root->scopeSpec.data(),root->memberSpec.data() ); if (Config::includeSourceFlag && !root->body.isEmpty()) { @@ -1789,6 +1875,31 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, parseFuncDecl(funcDecl,scopeName,classTempList,funcType,funcName, funcArgs,funcTempList,exceptions ); + //printf("scopeName=`%s'\n",scopeName.data()); + + bool isSpecialization = !root->scopeSpec.isEmpty() && + root->scopeSpec != tempArgListToString(root->tArgList); + + //printf("1. scopeName=`%s' specialization=%d\n", + // scopeName.data(),isSpecialization + // ); + // include template specifier in the scope if needed + if (!scopeName.isEmpty() && !root->scopeSpec.isEmpty() && isSpecialization) + { + //scopeName = insertTemplateSpecifierInScope( + // scopeName,removeRedundantWhiteSpace(root->scopeSpec)); + //printf("2. scopeName=`%s'\n",scopeName.data()); + } + + // if this is a member template inside non template class, the parser puts + // template specifier in scopeSepc, so we copy it to the right location here + if (scopeName.isEmpty() && !root->scopeSpec.isEmpty() && + root->memberSpec.isEmpty() && funcTempList.isEmpty() + ) + // template specifier that was found is for a function + { + funcTempList = root->scopeSpec; + } // the class name can also be a namespace name, we decide this later. // if a related class name is specified and the class name could @@ -1811,13 +1922,23 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, Entry *p=root->parent; while (p) // get full scope as class name { - //printf("++++++ scope=`%s'\n",p->name.data()); - if (((p->section & Entry::COMPOUND_MASK) || - p->section == Entry::NAMESPACE_SEC - ) && !p->name.isEmpty() && p->name[0]!='@' + if ((p->section & Entry::SCOPE_MASK) + && !p->name.isEmpty() && p->name[0]!='@' ) { - if (scopeName.left(p->name.length())==p->name) + //printf("p->name=`%s' scopeName=`%s' classTempList=%s\n", + // p->name.data(),scopeName.data(),classTempList.data()); + + QCString tryScope; + + if (scopeName.find('<')==-1 && !classTempList.isEmpty()) + tryScope=insertTemplateSpecifierInScope(scopeName,classTempList); + else + tryScope=scopeName.copy(); + + //printf("tryScope=%s\n",tryScope.data()); + + if (leftScopeMatch(tryScope,p->name)) break; // scope already present, so stop now // prepend name to scope if (!scopeName.isEmpty()) scopeName.prepend("::"); @@ -1825,14 +1946,20 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, } p=p->parent; } + //printf("3. scopeName=`%s'\n",scopeName.data()); + //printf("result: scope=%s\n",scopeName.data()); } - if (scopeName.length()>0 && scopeName.find('<')==-1 && classTempList.length()==0 ) - { // class is a template, but no template name list found - ClassDef *cd=getClass(scopeName); - if (cd) // class exists + if (!scopeName.isEmpty() && + scopeName.find('<')==-1 && + classTempList.length()==0 + ) + { + ClassDef *cd=getClass(scopeName); + // class is a template, but no template name list found + if (root->tArgList && cd && cd->templateArguments()) { - classTempList = cd->getTemplateNameString(); + classTempList = tempArgListToString(root->tArgList); } } @@ -1840,17 +1967,20 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, extractNamespaceName(scopeName,className,namespaceName); QCString tempScopeName=scopeName.copy(); - int ti; - int spi = namespaceName.isEmpty() ? 0 : namespaceName.length()+2; - if ((ti=tempScopeName.find("::",spi))!=-1 && !classTempList.isEmpty()) - { - // insert template parameters after the first scope name - tempScopeName=tempScopeName.left(ti)+classTempList+ - tempScopeName.right(tempScopeName.length()-ti); - } - else + int ti=tempScopeName.find('<'); + if (ti==-1) { - tempScopeName+=classTempList; + int spi = namespaceName.isEmpty() ? 0 : namespaceName.length()+2; + if ((ti=tempScopeName.find("::",spi))!=-1 && !classTempList.isEmpty()) + { + // insert template parameters after the first scope name + tempScopeName=tempScopeName.left(ti)+classTempList+ + tempScopeName.right(tempScopeName.length()-ti); + } + else + { + tempScopeName+=classTempList; + } } @@ -1958,33 +2088,54 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, isFunc ); - MemberName *mn; + MemberName *mn=0; if (funcName.length()>0) // function name is valid { - if (!isRelated && (mn=memberNameDict[funcName])) // function name already found + Debug::print(Debug::FindMembers,0, + "1. funcName=`%s'\n",funcName.data()); + //if (funcTempList.length()>0) // try with member specialization + //{ + // mn=memberNameDict[funcName+funcTempList]; + //} + if (mn==0) // try without specialization { + mn=memberNameDict[funcName]; + } + if (!isRelated && mn) // function name already found + { + Debug::print(Debug::FindMembers,0, + "2. member name exists \n"); if (className.length()>0) // class name is valid { int count=0; MemberDef *md=mn->first(); // for each member with that name while (md) { + Debug::print(Debug::FindMembers,0, + "3. member definition found scopeName=`%s'\n",scopeName.data()); ClassDef *cd=md->memberClass(); //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data()); ClassDef *tcd=0; if (classTempList.length()>0) // try to find the correct specialization { - tcd=getClass(scopeName+classTempList); - if (!tcd) tcd=getClass(scopeName); // try general class + tcd=getClass( + insertTemplateSpecifierInScope( + scopeName, + classTempList + ) + ); // try specialization } - else + if (tcd==0) { - tcd=getClass(scopeName); + tcd=getClass(scopeName); // try general class } if (cd && tcd==cd) // member's classes match { + Debug::print(Debug::FindMembers,0, + "4. class definition %s found\n",cd->name().data()); int ci; ArgumentList *classTemplArgs = cd->templateArguments(); + ArgumentList *funcTemplArgs = md->templateArguments(); if ((ci=cd->name().find("::"))!=-1) // nested class { ClassDef *parentClass = getClass(cd->name().left(ci)); @@ -1993,8 +2144,13 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, } //printf("cd->name=%s classTemplArgs=%s\n",cd->name().data(), // argListToString(classTemplArgs).data()); + ArgumentList *argList = 0; bool substDone=FALSE; + + /* substitute the occurrences of class template names in the + * argument list before matching + */ if (!classTempList.isEmpty() && classTemplArgs && md->argumentList() @@ -2019,17 +2175,53 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded, { argList = md->argumentList(); } + + /* substitute the occurrences of member template names in the + * argument list before matching + */ + if (!funcTempList.isEmpty() && + funcTemplArgs && + md->argumentList() + ) + { + ArgumentList *oldArgList = argList; + argList = new ArgumentList; + substituteTemplateArgNames( + oldArgList, /* source argument list */ + funcTempList, /* template names source */ + funcTemplArgs, /* template names dest */ + argList /* dest argument list */ + ); + if (substDone) // delete old argument list + delete oldArgList; + substDone=TRUE; + } + + Debug::print(Debug::FindMembers,0, + "5. matching `%s'<=>`%s' className=%s namespaceName=%s\n", + argListToString(argList).data(),argListToString(root->argList).data(), + className.data(),namespaceName.data() + ); + + // TODO: match loop for all possible scopes bool matching= md->isVariable() || md->isTypedef() || // needed for function pointers (md->argumentList()==0 && root->argList->count()==0) || matchArguments(argList, root->argList,className,namespaceName); + Debug::print(Debug::FindMembers,0, + "6. match results = %d\n",matching); + if (substDone) // found a new argument list { //printf("root->tArgList=`%s'\n",argListToString(root->tArgList).data()); if (matching) // replace member's argument list { - md->setScopeTemplateArguments(root->tArgList); + //printf("Setting scope template argument of member to %s\n", + // argListToString(root->tArgList).data() + // ); + md->setScopeDefTemplateArguments(root->tArgList); + md->setMemberDefTemplateArguments(root->mtArgList); md->setArgumentList(argList); } else // no match -> delete argument list @@ -2265,7 +2457,7 @@ void findMemberDocumentation(Entry *root) else if (root->section==Entry::FUNCTION_SEC && (!root->doc.isEmpty() || !root->brief.isEmpty() || - !root->body.isEmpty() /*|| Config::extractAllFlag*/ + !root->body.isEmpty() || root->mGrpId!=-1 /*|| Config::extractAllFlag*/ ) ) { @@ -2275,15 +2467,37 @@ void findMemberDocumentation(Entry *root) //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data()); if (root->type.length()>0) { - findMember(root, - root->type+" "+root->inside+root->name+root->args+root->exception, - root->relates, - FALSE,isFunc); + //if (root->tArgList && root->mtArgList) // add member template specifier + //{ + // findMember(root, + // root->type+" "+ + // root->inside+ + // root->name+ + // tempArgListToString(root->mtArgList)+ + // root->args+ + // root->exception, + // root->relates, + // FALSE,isFunc); + // + //else + // + findMember(root, + root->type+" "+ + root->inside+ + root->name+ + root->args+ + root->exception, + root->relates, + FALSE,isFunc); + //} } else { findMember(root, - root->inside+root->name+root->args+root->exception, + root->inside+ + root->name+ + root->args+ + root->exception, root->relates, FALSE,isFunc); } @@ -2586,7 +2800,7 @@ static void findDEV(const MemberNameList &mnl) // for each enum value while (fmd) { - if (fmd->hasDocumentation()) documentedEnumValues++; + if (fmd->isLinkableInProject()) documentedEnumValues++; fmd=fmdl->next(); } } @@ -2661,7 +2875,7 @@ void computeMemberRelations() { //printf(" match found!\n"); if (mcd && bmcd && - mcd->isVisibleExt() && bmcd->isVisibleExt() + mcd->isLinkable() && bmcd->isLinkable() ) { md->setReimplements(bmd); @@ -2866,7 +3080,7 @@ void generateFileDocs() FileDef *fd=fn->first(); while (fd) { - if (!fd->isReference() && fd->hasDocumentation()) + if (fd->isLinkableInProject()) { msg("Generating docs for file %s...\n",fd->name().data()); fd->writeDocumentation(*outputList); @@ -2891,13 +3105,19 @@ void generateClassDocs() msg("Generating index page...\n"); writeIndex(*outputList); - msg("Generating compound index...\n"); + msg("Generating annotated compound index...\n"); writeAnnotatedIndex(*outputList); + if (Config::alphaIndexFlag) + { + msg("Generating alphabetical compound index...\n"); + writeAlphabeticalIndex(*outputList); + } + msg("Generating hierarchical class index...\n"); writeHierarchicalIndex(*outputList); - if (includeFiles.count()>0) + if (documentedIncludeFiles>0) { msg("Generating header index...\n"); writeHeaderIndex(*outputList); @@ -2915,13 +3135,7 @@ void generateClassDocs() for ( ; cli.current() ; ++cli ) { ClassDef *cd=cli.current(); - if (!cd->isReference() && - //!cd->name().isEmpty() && - //cd->name().at(0)!='@' && - //(cd->protection()!=Private || Config::extractPrivateFlag) && - //(cd->hasDocumentation() || !Config::hideClassFlag) - cd->isVisible() - ) + if ( cd->isLinkableInProject() ) // skip external references and anonymous compounds { msg("Generating docs for compound %s...\n",cd->name().data()); @@ -2996,7 +3210,7 @@ void findDefineDocumentation(Entry *root) // root->startLine,root->fileName.data()); } } - else // define not found + else if (root->doc.length()>0 || root->brief.length()>0) // define not found { warn("Warning: documentation for unknown define %s found at line %d of " "file %s\n",root->name.data(),root->startLine,root->fileName.data()); @@ -3166,6 +3380,7 @@ void buildExampleList(Entry *root) void generateExampleDocs() { + outputList->disable(OutputGenerator::Man); PageInfo *pi=exampleList.first(); while (pi) { @@ -3177,6 +3392,7 @@ void generateExampleDocs() endFile(*outputList); pi=exampleList.next(); } + outputList->enable(OutputGenerator::Man); } //---------------------------------------------------------------------------- @@ -3194,6 +3410,34 @@ void generateGroupDocs() } //---------------------------------------------------------------------------- +// create member group documentation based on the documentation of the +// group's members. + +void computeMemberGroupDocumentation() +{ + MemberGroupDictIterator mgdi(memberGroupDict); + MemberGroup *mg; + for (;(mg=mgdi.current());++mgdi) + { + mg->addDocumentation(); + } +} + +//---------------------------------------------------------------------------- +// generate member group pages + +void generateMemberGroupDocs() +{ + MemberGroupDictIterator mgdi(memberGroupDict); + MemberGroup *mg; + for (;(mg=mgdi.current());++mgdi) + { + mg->writeDocumentation(*outputList); + } +} + + +//---------------------------------------------------------------------------- // generate module pages void generateNamespaceDocs() @@ -3204,8 +3448,7 @@ void generateNamespaceDocs() NamespaceDef *nd; for (;(nd=nli.current());++nli) { - if ((nd->getReference() || nd->hasDocumentation()) && - !nd->name().isEmpty() && nd->name().at(0)!='@') + if (nd->isLinkableInProject()) { msg("Generating docs for namespace %s\n",nd->name().data()); nd->writeDocumentation(*outputList); @@ -3524,9 +3767,10 @@ void readFiles(BufStr &output) } s=inputFiles.next(); + //printf("-------> adding new line\n"); + output.addChar('\n'); /* to prevent problems under Windows ? */ } // *p++='\0'; - output.addChar('\n'); /* to prevent problems under Windows ? */ output.addChar(0); //printf("Output after preprocessing:\n---------\n%s\n----------\n",output.data()); //printf("Final length = %d\n",p-output.data()); @@ -3835,7 +4079,7 @@ int main(int argc,char **argv) } } else - config=fileToString(argv[1]); + config=fileToString(argv[optind]); parseConfig(config); checkConfig(); @@ -3849,6 +4093,7 @@ int main(int argc,char **argv) { outputList->add(new HtmlGenerator); HtmlGenerator::init(); + if (Config::htmlHelpFlag) HtmlHelp::getInstance()->initialize(); } if (Config::generateLatex) { @@ -4016,7 +4261,6 @@ int main(int argc,char **argv) msg("Searching for member function documentation...\n"); findMemberDocumentation(root); // may introduce new members ! - msg("Freeing entry tree\n"); delete root; @@ -4035,6 +4279,9 @@ int main(int argc,char **argv) msg("Building full member lists recursively...\n"); buildCompleteMemberLists(); + msg("Determining member group documentation...\n"); + computeMemberGroupDocumentation(); + //unrelatedFunctionsUsed=hasUnrelatedFunctions(); /************************************************************************** @@ -4053,6 +4300,7 @@ int main(int argc,char **argv) documentedGroups = countGroups(); documentedNamespaces = countNamespaces(); documentedNamespaceMembers = countNamespaceMembers(); + documentedIncludeFiles = countIncludeFiles(); // compute the shortest possible names of all files // without loosing the uniqueness of the file names. @@ -4077,6 +4325,9 @@ int main(int argc,char **argv) msg("Generating group documentation...\n"); generateGroupDocs(); + msg("Generating member group documentation...\n"); + generateMemberGroupDocs(); + msg("Generating namespace index...\n"); generateNamespaceDocs(); @@ -4132,6 +4383,11 @@ int main(int argc,char **argv) Config::htmlOutputDir.data()); } + if (Config::generateHtml && Config::htmlHelpFlag) + { + HtmlHelp::getInstance()->finalize(); + } + delete tag; return 0; } diff --git a/src/doxygen.h b/src/doxygen.h index 17c8cd8..00803c0 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -74,11 +74,11 @@ class BufStr : public QCString const int spareRoom; // 10Kb extra room to avoid frequent resizing }; -typedef QList<QCString> StringList; +typedef QList<QCString> StringList; typedef QDict<MemberDef> MemberDict; typedef QDict<ClassDef> ClassDict; typedef QDict<FileDef> FileDict; -typedef QDict<QCString> StringDict; +typedef QDict<QCString> StringDict; typedef QDict<PageInfo> PageDict; typedef QDict<GroupDef> GroupDict; @@ -123,5 +123,6 @@ extern int documentedFiles; extern int documentedGroups; extern int documentedNamespaces; extern int documentedNamespaceMembers; +extern int documentedIncludeFiles; #endif diff --git a/src/doxygen.pro b/src/doxygen.pro.in index e6dd3c0..e36c7e2 100644 --- a/src/doxygen.pro +++ b/src/doxygen.pro.in @@ -14,7 +14,7 @@ # TMake project file for doxygen TEMPLATE = doxygen.t -CONFIG = console qt warn_on release #debug +CONFIG = console qt warn_on $extraopts HEADERS = doxygen.h scanner.h classdef.h classlist.h memberdef.h \ membername.h index.h memberlist.h definition.h \ entry.h logos.h instdox.h message.h code.h \ @@ -23,7 +23,7 @@ HEADERS = doxygen.h scanner.h classdef.h classlist.h memberdef.h \ filename.h defargs.h groupdef.h gifenc.h diagram.h image.h \ namespacedef.h version.h language.h translator.h \ translator_nl.h translator_se.h translator_cz.h translator_fr.h \ - translator_it.h formula.h debug.h + translator_it.h formula.h debug.h membergroup.h htmlhelp.h SOURCES = doxygen.cpp scanner.cpp classdef.cpp classlist.cpp memberdef.cpp \ membername.cpp index.cpp memberlist.cpp \ entry.cpp logos.cpp instdox.cpp message.cpp code.cpp \ @@ -32,7 +32,8 @@ SOURCES = doxygen.cpp scanner.cpp classdef.cpp classlist.cpp memberdef.cpp cppvalue.cpp ce_lex.cpp ce_parse.cpp pre.cpp \ tag.cpp filename.cpp declinfo.cpp defargs.cpp define.cpp \ diagram.cpp gifenc.cpp image.cpp namespacedef.cpp \ - version.cpp language.cpp definition.cpp formula.cpp debug.cpp + version.cpp language.cpp definition.cpp formula.cpp debug.cpp \ + membergroup.cpp htmlhelp.cpp win32:INCLUDEPATH += . TARGET = ../bin/doxygen OBJECTS_DIR = ../objects diff --git a/src/doxysearch.pro b/src/doxysearch.pro.in index ab34adc..f96daf9 100644 --- a/src/doxysearch.pro +++ b/src/doxysearch.pro.in @@ -12,7 +12,7 @@ # All output generated with Doxygen is not covered by this license. TEMPLATE = app.t -CONFIG = console warn_on release +CONFIG = console warn_on $extraopts SOURCES = doxysearch.cpp TARGET = ../bin/doxysearch OBJECTS_DIR = ../objects diff --git a/src/doxytag.l b/src/doxytag.l index 4e2debd..e56abed 100644 --- a/src/doxytag.l +++ b/src/doxytag.l @@ -324,14 +324,18 @@ QCString unhtmlify(const char *str) classFile=yytext; BEGIN( SearchMemberRef ); } -<SearchMemberRef>"#" { +<SearchMemberRef,ReadClassFile>"#" { + if (YY_START==ReadClassFile) + { + classFile=yyFileName; + } BEGIN( ReadMemberRef ); } <ReadMemberRef>[a-z_A-Z0-9]+ { memberRef=yytext; BEGIN( SearchMemberName ); } -<SearchMemberName>"<strong>" { +<SearchMemberName>"<strong>"|"<b>" { // <strong> is for qt-1.44, <b> is for qt-2.00 BEGIN( ReadMemberName ); } <SearchMemberName>[a-z_A-Z~] { diff --git a/src/doxytag.pro b/src/doxytag.pro.in index 3389c00..c09cad5 100644 --- a/src/doxytag.pro +++ b/src/doxytag.pro.in @@ -14,7 +14,7 @@ # TMake project file for doxytag TEMPLATE = doxytag.t -CONFIG = console warn_on qt release +CONFIG = console warn_on qt $extraopts HEADERS = suffixtree.h searchindex.h logos.h version.h SOURCES = doxytag.cpp suffixtree.cpp searchindex.cpp \ logos.cpp version.cpp diff --git a/src/entry.cpp b/src/entry.cpp index 4e2ca93..c330f8b 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -35,6 +35,7 @@ Entry::Entry() argList->setAutoDelete(TRUE); //printf("Entry::Entry() tArgList=0\n"); tArgList = 0; + mtArgList = 0; mGrpId = -1; reset(); } @@ -76,6 +77,7 @@ Entry::Entry(const Entry &e) argList->setAutoDelete(TRUE); //printf("Entry::Entry(copy) tArgList=0\n"); tArgList = 0; + mtArgList = 0; // deep copy of the child entry list QListIterator<Entry> eli(*e.sublist); @@ -131,6 +133,20 @@ Entry::Entry(const Entry &e) //printf("appending argument %s %s\n",a->type.data(),a->name.data()); } } + + // deep copy template argument list + if (e.mtArgList) + { + mtArgList = new ArgumentList; + mtArgList->setAutoDelete(TRUE); + //printf("Entry::Entry(copy) new tArgList=%p\n",tArgList); + QListIterator<Argument> mtali(*e.mtArgList); + for (;(a=mtali.current());++mtali) + { + mtArgList->append(new Argument(*a)); + //printf("appending argument %s %s\n",a->type.data(),a->name.data()); + } + } } Entry::~Entry() @@ -143,6 +159,7 @@ Entry::~Entry() delete anchors; delete argList; delete tArgList; + delete mtArgList; num--; } @@ -181,6 +198,8 @@ void Entry::reset() brief.resize(0); inside.resize(0); fileName.resize(0); + scopeSpec.resize(0); + memberSpec.resize(0); mGrpId = -1; section = EMPTY_SEC; sig = FALSE; @@ -195,6 +214,7 @@ void Entry::reset() anchors->clear(); argList->clear(); if (tArgList) { delete tArgList; tArgList=0; } + if (mtArgList) { delete mtArgList; mtArgList=0; } } @@ -262,5 +282,17 @@ int Entry::getSize() a=tArgList->next(); } } + if (mtArgList) + { + a=mtArgList->first(); + while (e) + { + size+=sizeof(Argument); + size+=a->type.length()+1 + +a->name.length()+1 + +a->defval.length()+1; + a=mtArgList->next(); + } + } return size; } diff --git a/src/entry.h b/src/entry.h index 94cf52b..18ee013 100644 --- a/src/entry.h +++ b/src/entry.h @@ -36,6 +36,7 @@ struct Argument Argument() {} Argument(const Argument &a) { + attrib=a.attrib.copy(); type=a.type.copy(); name=a.name.copy(); defval=a.defval.copy(); @@ -44,6 +45,7 @@ struct Argument { if (this!=&a) { + attrib=a.attrib.copy(); type=a.type.copy(); name=a.name.copy(); defval=a.defval.copy(); @@ -51,6 +53,7 @@ struct Argument return *this; } + QCString attrib; // argument attribute (IDL only) QCString type; // argument type QCString name; // argument name (if any) QCString defval; // argument default value (if any) @@ -101,8 +104,10 @@ class Entry GROUPDOC_SEC = 0x00800000, NAMESPACE_SEC = 0x01000000, NAMESPACEDOC_SEC = 0x02000000, - COMPOUND_MASK = CLASS_SEC | STRUCT_SEC | UNION_SEC, - COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC, + INTERFACE_SEC = 0x04000000, + INTERFACEDOC_SEC = 0x08000000, + COMPOUND_MASK = CLASS_SEC | STRUCT_SEC | UNION_SEC | INTERFACE_SEC, + COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC | INTERFACEDOC_SEC, SCOPE_MASK = COMPOUND_MASK | NAMESPACE_SEC, FILE_MASK = SOURCE_SEC | HEADER_SEC }; @@ -128,6 +133,9 @@ class Entry QCString args; // member argument string ArgumentList *argList; // member arguments as a list ArgumentList *tArgList; // template argument list + ArgumentList *mtArgList; // member template argument list + QCString scopeSpec; // template specialization of the scope + QCString memberSpec; // template specialization of the member QCString program; // the program text QCString body; // the function body QCString includeFile; // include file (2 arg of \class, must be unique) @@ -138,7 +146,6 @@ class Entry QCString inside; // name of the class in which documents are found QCString exception; // throw specification int mGrpId; // member group id - QCString mGrpHeader; // member group header QList<Entry> *sublist; // entries that are children of this one QList<BaseInfo> *extends; // list of base classes QList<QCString> *groups; // list of groups this entry belongs to diff --git a/src/filedef.cpp b/src/filedef.cpp index 5f62357..f038e2e 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -37,12 +37,13 @@ FileDef::FileDef(const char *p,const char *nm,const char *ref) path=p; filepath=path+nm; filename=nameToFile(nm); - reference=ref; + setReference(ref); memList = new MemberList; classList = new ClassList; includeList = new FileList; defineList = new DefineList; namespaceList = new NamespaceList; + namespaceDict = new NamespaceDict(7); } /*! destroy the file definition */ @@ -52,6 +53,8 @@ FileDef::~FileDef() delete classList; delete includeList; delete defineList; + delete namespaceList; + delete namespaceDict; } /*! Compute the HTML anchor names for all members in the class */ @@ -105,7 +108,7 @@ void FileDef::writeDocumentation(OutputList &ol) bool found=FALSE; while (nd) { - if (nd->isVisibleExt()) + if (nd->name().find('@')==-1) { if (!found) { @@ -115,16 +118,16 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startMemberList(); found=TRUE; } - ol.startMemberItem(); + ol.startMemberItem(FALSE,0); ol.writeString("namespace "); ol.insertMemberAlign(); - if (nd->hasDocumentation()) + if (nd->isLinkable()) { ol.writeObjectLink(nd->getReference(), - nd->getOutputFileBase(), - 0, - nd->name() - ); + nd->getOutputFileBase(), + 0, + nd->name() + ); } else { @@ -132,7 +135,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.docify(nd->name()); ol.endBold(); } - ol.endMemberItem(); + ol.endMemberItem(FALSE,0,0,FALSE); } nd=namespaceList->next(); } @@ -144,7 +147,7 @@ void FileDef::writeDocumentation(OutputList &ol) bool found=FALSE; while (cd) { - if ( cd->isVisibleExt() ) + if (cd->name().find('@')==-1) { if (!found) { @@ -154,22 +157,23 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startMemberList(); found=TRUE; } - ol.startMemberItem(); + ol.startMemberItem(FALSE,FALSE); switch (cd->compoundType()) { case ClassDef::Class: ol.writeString("class"); break; case ClassDef::Struct: ol.writeString("struct"); break; case ClassDef::Union: ol.writeString("union"); break; + case ClassDef::Interface: ol.writeString("interface"); break; } ol.writeString(" "); ol.insertMemberAlign(); - if (cd->hasDocumentation()) + if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(), - cd->getOutputFileBase(), - 0, - cd->name() - ); + cd->getOutputFileBase(), + 0, + cd->name() + ); } else { @@ -177,14 +181,14 @@ void FileDef::writeDocumentation(OutputList &ol) ol.docify(cd->name()); ol.endBold(); } - ol.endMemberItem(); + ol.endMemberItem(FALSE,0,0,FALSE); } cd=classList->next(); + if (found) ol.endMemberList(); } - if (found) ol.endMemberList(); } - writeMemberDecs(ol,0,0,this,0,0,memList); + memList->writeDeclarations(ol,0,0,this,0,0); ol.endMemberSections(); //doc=doc.stripWhiteSpace(); @@ -222,7 +226,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trDefineDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Define); + memList->writeDocumentation(ol,name(),MemberDef::Define); } if ( memList->protoCount()>0 ) @@ -231,7 +235,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trFunctionPrototypeDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Prototype); + memList->writeDocumentation(ol,name(),MemberDef::Prototype); } if ( memList->typedefCount()>0 ) @@ -240,7 +244,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trTypedefDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Typedef); + memList->writeDocumentation(ol,name(),MemberDef::Typedef); } if ( memList->enumCount()>0 ) @@ -249,7 +253,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trEnumerationTypeDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Enumeration); + memList->writeDocumentation(ol,name(),MemberDef::Enumeration); } if ( memList->enumValueCount()>0 ) @@ -258,16 +262,19 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trEnumerationValueDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::EnumValue); + memList->writeDocumentation(ol,name(),MemberDef::EnumValue); } - if ( memList->funcCount()>0 ) + int cnt; + if ( (cnt=memList->funcCount()>0) ) { ol.writeRuler(); ol.startGroupHeader(); - parseText(ol,theTranslator->trFunctionDocumentation()); + QCString cntString; + cntString.sprintf(" (%d)",cnt); + parseText(ol,theTranslator->trFunctionDocumentation()+cntString); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Function); + memList->writeDocumentation(ol,name(),MemberDef::Function); } if ( memList->varCount()>0 ) @@ -276,7 +283,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trVariableDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Variable); + memList->writeDocumentation(ol,name(),MemberDef::Variable); } // write Author section (Man only) @@ -304,7 +311,11 @@ void FileDef::insertClass(ClassDef *cd) /*! Adds namespace definition \a nd to the list of all compounds of this file */ void FileDef::insertNamespace(NamespaceDef *nd) { - namespaceList->append(nd); + if (!nd->name().isEmpty() && namespaceDict->find(nd->name())==0) + { + namespaceList->append(nd); + namespaceDict->insert(nd->name(),nd); + } } //----------------------------------------------------------------------------- diff --git a/src/filedef.h b/src/filedef.h index b5c9585..6f39be2 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -31,6 +31,7 @@ class OutputList; class DefineList; class NamespaceDef; class NamespaceList; +class NamespaceDict; /*! \class FileDef filedef.h \brief A File definition. @@ -95,15 +96,26 @@ class FileDef : public Definition /*! Returns true iff this file was externally defined (i.e. read from a tag file) */ - bool isReference() { return !reference.isNull(); } + //bool isReference() { return !reference.isNull(); } /*! Returns the reference name of the external file, if any or 0 if the file is not defined. */ - const char *getReference() { return reference; } + //const char *getReference() { return reference; } //void setFileType(FileType ft) { ftype = ft; } //FileType fileType() const { return ftype; } + bool isLinkableInProject() + { + return hasDocumentation() && !isReference(); + } + + bool isLinkable() + { + return isLinkableInProject() || isReference(); + } + + void writeDocumentation(OutputList &ol); friend void generatedFileNames(); void insertMember(MemberDef *fd); @@ -115,12 +127,13 @@ class FileDef : public Definition MemberList *memList; ClassList *classList; FileList *includeList; + NamespaceDict *namespaceDict; NamespaceList *namespaceList; DefineList *defineList; //QCString n; //QCString doc; //QCString brief; - QCString reference; + //QCString reference; QCString path; QCString filepath; QCString diskname; diff --git a/src/formula.cpp b/src/formula.cpp index 0a961ca..68e74f8 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -150,11 +150,19 @@ void FormulaList::generateBitmaps(const char *path) // Then we run ghostscript to convert the postscript to a pixmap // The pixmap is a truecolor image, where only black and white are // used. +#ifdef _WIN32 + sprintf(gsCmd,"gswin32 -q -g%dx%d -r%dx%dx -sDEVICE=ppmraw " + "-sOutputFile=%s.pnm -DNOPAUSE -- %s.ps", + gx,gy,(int)(scaleFactor*72),(int)(scaleFactor*72), + formBase.data(),formBase.data() + ); +#else sprintf(gsCmd,"gs -q -g%dx%d -r%dx%dx -sDEVICE=ppmraw " "-sOutputFile=%s.pnm -DNOPAUSE -- %s.ps", gx,gy,(int)(scaleFactor*72),(int)(scaleFactor*72), formBase.data(),formBase.data() ); +#endif //printf("Running ghostscript...\n"); system(gsCmd); f.setName(formBase+".pnm"); diff --git a/src/groupdef.cpp b/src/groupdef.cpp index e1e28ab..6f0133a 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -122,9 +122,10 @@ void GroupDef::writeDocumentation(OutputList &ol) QCString type; switch (cd->compoundType()) { - case ClassDef::Class: type="class"; break; - case ClassDef::Struct: type="struct"; break; - case ClassDef::Union: type="union"; break; + case ClassDef::Class: type="class"; break; + case ClassDef::Struct: type="struct"; break; + case ClassDef::Union: type="union"; break; + case ClassDef::Interface: type="interface"; break; } ol.writeStartAnnoItem(type,cd->getOutputFileBase(),0,cd->name()); ol.writeEndAnnoItem(cd->name()); diff --git a/src/groupdef.h b/src/groupdef.h index ab54ea6..7b774d3 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -43,6 +43,14 @@ class GroupDef : public Definition void addNamespace(const NamespaceDef *def); void writeDocumentation(OutputList &ol); int countMembers() const; + bool isLinkableInProject() + { + return hasDocumentation() && !isReference(); + } + bool isLinkable() + { + return isLinkableInProject() || isReference(); + } private: QCString title; // title of the group diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 1a44646..53b20b9 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -26,6 +26,10 @@ #include "logos.h" #include "diagram.h" +#define GROUP_COLOR "#ff8080" + +HtmlHelp *HtmlGenerator::htmlHelp = 0; + HtmlGenerator::HtmlGenerator() : OutputGenerator() { if (Config::headerFile.length()>0) header=fileToString(Config::headerFile); @@ -51,6 +55,7 @@ void HtmlGenerator::init() exit(1); } writeLogo(Config::htmlOutputDir); + writeNullImage(Config::htmlOutputDir); } void HtmlGenerator::startFile(const char *name,const char *title,bool external) @@ -59,6 +64,7 @@ void HtmlGenerator::startFile(const char *name,const char *title,bool external) lastTitle=title; if (fileName.right(5)!=".html") fileName+=".html"; startPlainFile(fileName); + lastFile = fileName; if (header.length()==0) { t << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" @@ -158,14 +164,16 @@ void HtmlGenerator::writeStyleInfo(int part) if (part==0) { startPlainFile("doxygen.css"); - t //<< "H1 { border-width: thin; border: solid; text-align: center }" << endl - << "H1 { text-align: center }" << endl - << "A.el { text-decoration: none; font-weight: bold }" << endl - << "DL.el { margin-left: -1cm }" << endl - << "DIV.fragment { width: 100%; border: none; background-color: #eeeeee }" << endl - << "DIV.in { margin-left: 16 }" << endl - << endl; + t << "H1 { text-align: center }" << endl; + t << "A.el { text-decoration: none; font-weight: bold }" << endl; + t << "DL.el { margin-left: -1cm }" << endl; + t << "DIV.fragment { width: 100%; border: none; background-color: #eeeeee }" << endl; + t << "DIV.in { margin-left: 16 }" << endl; + t << "A.gl:link { color: #ffffff }" << endl; + t << "A.gl:visited { color: #ffffff }" << endl; + t << "A.gl { text-decoration: none; font-weight: bold; background-color: " << GROUP_COLOR << " }" << endl; + t << endl; endPlainFile(); } } @@ -209,6 +217,10 @@ void HtmlGenerator::writeIndexItem(const char *ref,const char *f, { t << "</b>"; } + //if (Config::htmlHelpFlag && f) + //{ + // htmlHelp->addItem(name,((QCString)f)+".html"); + //} } void HtmlGenerator::writeStartAnnoItem(const char *,const char *f, @@ -219,6 +231,10 @@ void HtmlGenerator::writeStartAnnoItem(const char *,const char *f, t << "<a class=\"el\" href=\"" << f << ".html\">"; docify(name); t << "</a> "; + //if (Config::htmlHelpFlag && f) + //{ + // htmlHelp->addItem(name, ((QCString)f)+".html"); + //} } void HtmlGenerator::writeObjectLink(const char *ref,const char *f, @@ -232,6 +248,10 @@ void HtmlGenerator::writeObjectLink(const char *ref,const char *f, t << "\">"; docify(name); t << "</a>"; + //if (Config::htmlHelpFlag && f && htmlHelp->depth()>0) + //{ + // htmlHelp->addItem(name,((QCString)f)+".html"); + //} } void HtmlGenerator::startTextLink(const char *f,const char *anchor) @@ -401,11 +421,26 @@ void HtmlGenerator::endMemberList() } } -void HtmlGenerator::startMemberItem() +// annonymous type: +// 0 = single column right aligned +// 1 = double column left aligned +// 2 = single column left aligned +void HtmlGenerator::startMemberItem(bool inGroup,int annoType) { if (Config::htmlAlignMemberFlag) { - t << "<tr><td align=right valign=top>"; + t << "<tr>"; + if (inGroup) + t << "<td bgcolor=\"" << GROUP_COLOR << "\">"; + else + t << "<td>"; + t << "<img src=\"null.gif\"></td><td><img src=\"null.gif\"></td>"; + switch(annoType) + { + case 0: t << "<td nowrap align=right valign=top>"; break; + case 1: t << "<td nowrap>"; break; + default: t << "<td nowrap valign=top>"; break; + } } else { @@ -413,28 +448,45 @@ void HtmlGenerator::startMemberItem() } } -void HtmlGenerator::insertMemberAlign() +void HtmlGenerator::endMemberItem(bool inGroup, + const char *fileName,const char *headerName,bool) { if (Config::htmlAlignMemberFlag) { - t << " </td><td valign=top>"; + if (inGroup) + { + t << " </td><td"; + if (headerName) + { + t << " align=right valign=top><a class=\"gl\" href=\"" + << fileName << ".html\"> " << headerName << " </a>"; + } + else + { + t << ">"; + } + t << "</td><td bgcolor=\"" << GROUP_COLOR + << "\"><img src=\"null.gif\">"; + } + t << "</td></tr>"; } + t << endl; } -void HtmlGenerator::endMemberItem() +void HtmlGenerator::insertMemberAlign() { if (Config::htmlAlignMemberFlag) { - t << "</td></tr>"; + t << " </td><td valign=top>"; } - t << endl; } void HtmlGenerator::startMemberDescription() { if (Config::htmlAlignMemberFlag) { - t << "<tr><td></td><td><font size=-1><em>"; + t << "<tr><td><img src=null.gif></td><td><img src=null.gif></td>" + "<td></td><td><font size=-1><em>"; } else { @@ -458,7 +510,7 @@ void HtmlGenerator::startMemberSections() { if (Config::htmlAlignMemberFlag) { - t << "<table border=0 cellpadding=0 cellspacing=1>" << endl; + t << "<table border=0 cellpadding=0 cellspacing=0>" << endl; } } @@ -474,7 +526,7 @@ void HtmlGenerator::startMemberHeader() { if (Config::htmlAlignMemberFlag) { - t << "<tr><td colspan=2><br><h2>"; + t << "<tr><td colspan=4><br><h2>"; } else { @@ -494,9 +546,35 @@ void HtmlGenerator::endMemberHeader() } } +void HtmlGenerator::memberGroupSpacing(bool inGroup) +{ + t << "<tr><td"; + if (inGroup) + { + // left vertical table line + t << " bgcolor=\"" << GROUP_COLOR << "\" height=1><img src=\"null.gif\">" + // white space + "</td><td colspan=4></td>" + // right vertical table line + "<td bgcolor=\"" << GROUP_COLOR << "\"><img src=\"null.gif\">"; + } + else + { + // one pixel height of whitespace + t << " height=1>"; + } + t << "</td></tr>" << endl; +} + +void HtmlGenerator::memberGroupSeparator() +{ + t << "<tr><td colspan=6 height=1 bgcolor=\"" << GROUP_COLOR + << "\"><img src=\"null.gif\"></td></tr>" << endl; +} + void HtmlGenerator::startMemberSubtitle() { - if (Config::htmlAlignMemberFlag) t << "<tr><td colspan=2>"; + if (Config::htmlAlignMemberFlag) t << "<tr><td colspan=4>"; } void HtmlGenerator::endMemberSubtitle() @@ -504,3 +582,36 @@ void HtmlGenerator::endMemberSubtitle() if (Config::htmlAlignMemberFlag) t << "<br><br></td></tr>" << endl; } +void HtmlGenerator::startIndexList() +{ + t << "<ul>" << endl; + //if (Config::htmlHelpFlag) + //{ + // if (htmlHelp->depth()==0) htmlHelp->addItem(lastTitle,lastFile); + // htmlHelp->incDepth(); + //} +} + +void HtmlGenerator::endIndexList() +{ + t << "</ul>" << endl; + //if (Config::htmlHelpFlag) + //{ + // htmlHelp->decDepth(); + //} +} + +void HtmlGenerator::startAlfabeticalIndexList() +{ + t << "<multicol cols=5><dl compact>" << endl; +} + +void HtmlGenerator::endAlfabeticalIndexList() +{ + t << "</dl></multicol>" << endl; +} + +void HtmlGenerator::writeIndexHeading(const char *s) +{ + t << "<dt><b><big>" << s << "</big></b><dd>" << endl; +} diff --git a/src/htmlgen.h b/src/htmlgen.h index 5eb4484..f742761 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -21,6 +21,7 @@ #include "outputgen.h" class QFile; +class HtmlHelp; class HtmlGenerator : public OutputGenerator { @@ -40,6 +41,7 @@ class HtmlGenerator : public OutputGenerator OutputGenerator *get(OutputType o) { return (o==Html) ? this : 0; } static void init(); + //void generateExternalIndex(); void startFile(const char *name,const char *title,bool external); void writeFooter(int,bool); @@ -59,12 +61,15 @@ class HtmlGenerator : public OutputGenerator void newParagraph(); void writeString(const char *text); - void startIndexList() { t << "<ul>" << endl; } - void endIndexList() { t << "</ul>" << endl; } + void startIndexList(); + void endIndexList(); void startItemList() { t << "<ul>" << endl; } void endItemList() { t << "</ul>" << endl; } void startEnumList() { t << "<ol>" << endl; } void endEnumList() { t << "</ol>" << endl; } + void startAlfabeticalIndexList(); + void endAlfabeticalIndexList(); + void writeIndexHeading(const char *s); void writeIndexItem(const char *ref,const char *file,const char *name); void docify(const char *text); void codify(const char *text); @@ -90,9 +95,11 @@ class HtmlGenerator : public OutputGenerator void endMemberSubtitle(); void startMemberList(); void endMemberList(); - void startMemberItem(); + void startMemberItem(bool,int); + void memberGroupSpacing(bool inGroup); + void memberGroupSeparator(); void insertMemberAlign(); - void endMemberItem(); + void endMemberItem(bool,const char *,const char *,bool); void startMemberDescription(); void endMemberDescription(); @@ -115,7 +122,7 @@ class HtmlGenerator : public OutputGenerator void writeChar(char c); void startMemberDoc(const char *,const char *,const char *) { t << endl << "<h3>"; } - void endMemberDoc() { t << "</h3>" << endl; } + void endMemberDoc() { t << "</h3>" << endl; } void writeDoxyAnchor(const char *clName,const char *anchor, const char *name); void writeLatexSpacing() {} @@ -168,6 +175,7 @@ class HtmlGenerator : public OutputGenerator void startQuickIndexItem(const char *,const char *); void endQuickIndexItem(); void writeFormula(const char *,const char *); + void writeNonBreakableSpace() { t << " "; } //static void docifyStatic(QTextStream &t,const char *str); @@ -175,9 +183,12 @@ class HtmlGenerator : public OutputGenerator QCString header; QCString footer; QCString lastTitle; + QCString lastFile; HtmlGenerator &operator=(const HtmlGenerator &g); HtmlGenerator(const HtmlGenerator &g); + + static HtmlHelp *htmlHelp; }; #endif diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp new file mode 100644 index 0000000..b1aed98 --- /dev/null +++ b/src/htmlhelp.cpp @@ -0,0 +1,381 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 1997-1999 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * All output generated with Doxygen is not covered by this license. + * + * The code is this file is largely based on a contribution from + * Harm van der Heijden <H.v.d.Heijden@phys.tue.nl> + * Please send thanks to him and bug reports to me :-) + */ + +#include <stdio.h> +#include <stdlib.h> +#include <qlist.h> +#include <qdict.h> + +#include "htmlhelp.h" +#include "config.h" +#include "message.h" + +//---------------------------------------------------------------------------- + +struct IndexField +{ + QCString name; + QCString url; + QCString anchor; + bool link; +}; + +class IndexFieldList : public QList<IndexField> +{ + public: + int compareItems(GCI item1, GCI item2) + { + return stricmp(((IndexField *)item1)->name,((IndexField *)item2)->name); + } +}; + +class IndexFieldListIterator : public QListIterator<IndexField> +{ + public: + IndexFieldListIterator( const IndexFieldList &list) : + QListIterator<IndexField>(list) {} +}; + +class IndexFieldDict : public QDict<IndexField> +{ + public: + IndexFieldDict(int size) : QDict<IndexField>(size) {} +}; + +/*! A helper class for HtmlHelp that manages a two level index in + * alphabetical order + */ +class HtmlHelpIndex +{ + public: + HtmlHelpIndex(); + ~HtmlHelpIndex(); + void addItem(const char *first,const char *second, + const char *url, const char *anchor,bool hasLink); + void writeFields(QTextStream &t); + private: + IndexFieldList *list; + IndexFieldDict *dict; +}; + +/*! Constructs a new HtmlHelp index */ +HtmlHelpIndex::HtmlHelpIndex() +{ + list = new IndexFieldList; + dict = new IndexFieldDict(10007); + list->setAutoDelete(TRUE); +} + +/*! Destroys the HtmlHelp index */ +HtmlHelpIndex::~HtmlHelpIndex() +{ + delete list; + delete dict; +} + +/*! Stores an item in the index if it is not already present. + * Items are stored in alphetical order, by sorting on the + * concatenation of \a level1 and \a level2 (if present). + * + * \param level1 the string at level 1 in the index. + * \param level2 the string at level 2 in the index (or 0 if not applicable). + * \param url the url of the documentation (without .html extension). + * \param anchor the anchor of the documentation within the page. + * \param hasLink if true, the url (without anchor) can be used in the + * level1 item, when writing the header of a list of level2 items. + */ +void HtmlHelpIndex::addItem(const char *level1,const char *level2, + const char *url,const char *anchor,bool hasLink) +{ + QCString key = level1; + if (level2) key+= (QCString)"?" + level2; + if (dict->find(key)==0) // new key + { + //printf(">>>>>>>>> HtmlHelpIndex::addItem(%s,%s,%s,%s)\n", + // level1,level2,url,anchor); + IndexField *f = new IndexField; + f->name = key; + f->url = url; + f->anchor = anchor; + f->link = hasLink; + list->inSort(f); + dict->insert(key,f); + } +} + +/*! Writes the sorted list of index items into a html like list. + * + * An list of calls with <code>name = level1,level2</code> as follows: + * <pre> + * a1,b1 + * a1,b2 + * a2,b1 + * a2,b2 + * a3 + * a4,b1 + * </pre> + * + * Will result in the following list: + * + * <pre> + * a1 -> link to url if hasLink==TRUE + * b1 -> link to url#anchor + * b2 -> link to url#anchor + * a2 -> link to url if hasLink==TRUE + * b1 -> link to url#anchor + * b2 -> link to url#anchor + * a3 -> link to url if hasLink==TRUE + * a4 -> link to url if hasLink==TRUE + * b1 -> link to url#anchor + * </pre> + */ +void HtmlHelpIndex::writeFields(QTextStream &t) +{ + IndexFieldListIterator ifli(*list); + IndexField *f; + QCString lastLevel1; + bool level2Started=FALSE; + for (;(f=ifli.current());++ifli) + { + QCString level1,level2; + int i; + if ((i=f->name.find('?'))!=-1) + { + level1 = f->name.left(i); + level2 = f->name.right(f->name.length()-i-1); + } + else + { + level1 = f->name.copy(); + } + + if (level1!=lastLevel1) + { // finish old list at level 2 + if (level2Started) t << " </UL>" << endl; + level2Started=FALSE; + + if (level2.isEmpty()) + { + t << " <LI><OBJECT type=\"text/sitemap\">"; + t << "<param name=\"Local\" value=\"" << f->url << ".html"; + if (!f->anchor.isEmpty()) t << "#" << f->anchor; + t << "\">"; + t << "<param name=\"Name\" value=\"" << level1 << "\">" + "</OBJECT>\n"; + } + else + { + if (f->link) + { + t << " <LI><OBJECT type=\"text/sitemap\">"; + t << "<param name=\"Local\" value=\"" << f->url << ".html\">"; + t << "<param name=\"Name\" value=\"" << level1 << "\">" + "</OBJECT>\n"; + } + else + { + t << " <LI><OBJECT type=\"text/sitemap\">"; + t << "<param name=\"See Also\" value=\"" << level1 << "\">"; + t << "<param name=\"Name\" value=\"" << level1 << "\">" + "</OBJECT>\n"; + } + } + } + if (!level2Started && !level2.isEmpty()) + { // start new list at level 2 + t << " <UL>" << endl; + level2Started=TRUE; + } + else if (level2Started && level2.isEmpty()) + { // end list at level 2 + t << " </UL>" << endl; + level2Started=FALSE; + } + if (level2Started) + { + t << " <LI><OBJECT type=\"text/sitemap\">"; + t << "<param name=\"Local\" value=\"" << f->url << ".html"; + if (!f->anchor.isEmpty()) t << "#" << f->anchor; + t << "\">"; + t << "<param name=\"Name\" value=\"" << level2 << "\">" + "</OBJECT>\n"; + } + lastLevel1 = level1.copy(); + } +} + +//---------------------------------------------------------------------------- + +HtmlHelp *HtmlHelp::theInstance = 0; + +/*! Constructs an html object. + * The object has to be \link initialize() initialized\endlink before it can + * be used. + */ +HtmlHelp::HtmlHelp() +{ + /* initial depth */ + dc = 0; + cf = kf = 0; + index = new HtmlHelpIndex; +} + +/*! return a reference to the one and only instance of this class. + */ +HtmlHelp *HtmlHelp::getInstance() +{ + if (theInstance==0) theInstance = new HtmlHelp; + return theInstance; +} + +/*! This will create a contents file (index.hhc) and a index file (index.hhk) + * and write the header of those files. + * It also creates a project file (index.hhp) + * \sa finalize() + */ +void HtmlHelp::initialize() +{ + /* open the contents file */ + QCString fName = Config::htmlOutputDir + "/index.hhc"; + cf = new QFile(fName); + if (!cf->open(IO_WriteOnly)) + { + err("Could not open file %s for writing\n",fName.data()); + exit(1); + } + /* Write the header of the contents file */ + cts.setDevice(cf); + cts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" + "<HTML><HEAD></HEAD><BODY>\n" + "<OBJECT type=\"text/site properties\">\n" + "<param name=\"ImageType\" value=\"Folder\">\n" + "</OBJECT>\n" + "<UL>\n"; + + /* open the contents file */ + fName = Config::htmlOutputDir + "/index.hhk"; + kf = new QFile(fName); + if (!kf->open(IO_WriteOnly)) + { + err("Could not open file %s for writing\n",fName.data()); + exit(1); + } + /* Write the header of the contents file */ + kts.setDevice(kf); + kts << "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n" + "<HTML><HEAD></HEAD><BODY>\n" + "<OBJECT type=\"text/site properties\">\n" + "<param name=\"ImageType\" value=\"Folder\">\n" + "</OBJECT>\n" + "<UL>\n"; + + /* Write the project file */ + fName = Config::htmlOutputDir + "/index.hhp"; + QFile f(fName); + if (f.open(IO_WriteOnly)) + { + QTextStream t(&f); + t << "[OPTIONS]\n" + "Compatibility=1.1\n" + "Full-text search=Yes\n" + "Contents file=index.hhc\n" + "Default Window=indexHelp\n" + "Default topic=index.html\n" + "Index file=index.hhk\n" + "Title=" << Config::projectName << endl << endl + << "[FILES]\n" + "index.html"; + f.close(); + } + else + { + err("Could not open file %s for writing\n",fName.data()); + } +} + +/*! Finalizes the HTML help. This will finish and close the + * contents file (index.hhc) and the index file (index.hhk). + * \sa initialize() + */ +void HtmlHelp::finalize() +{ + // end the contents file + cts << "</UL>\n"; + cts.unsetDevice(); + cf->close(); + delete cf; + + index->writeFields(kts); + + // end the index file + kts << "</UL>\n"; + kts.unsetDevice(); + kf->close(); + delete kf; +} + +/*! Increase the level of the contents hierarchy. + * This will start a new unnumbered HTML list in contents file. + * \sa decContentsDepth() + */ +int HtmlHelp::incContentsDepth() +{ + int i; for (i=0;i<dc+1;i++) cts << " "; + cts << "<UL>\n"; + return ++dc; +} + +/*! Decrease the level of the contents hierarchy. + * This will end the unnumber HTML list. + * \sa incContentsDepth() + */ +int HtmlHelp::decContentsDepth() +{ + int i; for (i=0;i<dc;i++) cts << " "; + cts << "</UL>\n"; + return --dc; +} + +/*! Add an list item to the contents file. + * \param name the name of the item. + * \param ref the URL of to the item. + */ +void HtmlHelp::addContentsItem(const char *name,const char *ref, + const char *anchor) +{ + int i; for (i=0;i<dc;i++) cts << " "; + cts << "<LI><OBJECT type=\"text/sitemap\">"; + cts << "<param name=\"Local\" value=\"" << ref << ".html"; + if (anchor) cts << "#" << anchor; + cts << "\">"; + cts << "<param name=\"Name\" value=\"" << name << "\">" + "</OBJECT>\n"; +} + +/*! Add an list item to the index file. + * \param name the name of the item. + * \param ref the URL of to the item. + * \sa HtmlHelpIndex + */ +void HtmlHelp::addIndexItem(const char *level1, const char *level2, + const char *ref, const char *anchor) +{ + index->addItem(level1,level2,ref,anchor,TRUE); + index->addItem(level2,level1,ref,anchor,FALSE); +} diff --git a/src/htmlhelp.h b/src/htmlhelp.h new file mode 100644 index 0000000..5856f3c --- /dev/null +++ b/src/htmlhelp.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 1997-1999 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * All output generated with Doxygen is not covered by this license. + * + * The code is this file is largely based on a contribution from + * Harm van der Heijden <H.v.d.Heijden@phys.tue.nl> + * Please send thanks to him and bug reports to me :-) + */ + +#ifndef HTMLHELP_H +#define HTMLHELP_H + +#include "qtbc.h" +#include <qtstream.h> + +class QFile; +class HtmlHelpIndex; + +/*! A class that generated the HTML Help specific files. + * These files can be used with the Microsoft HTML Help workshop + * to generate compressed HTML files (.chm). + */ +class HtmlHelp +{ + public: + static HtmlHelp *getInstance(); + void initialize(); + void finalize(); + int incContentsDepth(); + int decContentsDepth(); + /*! return the current depth of the contents tree */ + int contentsDepth() { return dc; } + void addContentsItem(const char *name, const char *ref, + const char *anchor = 0); + void addIndexItem(const char *level1, const char *level2, + const char *ref, const char *anchor); + private: + HtmlHelp(); + QFile *cf,*kf; + QTextStream cts,kts; + HtmlHelpIndex *index; + int dc; + static HtmlHelp *theInstance; +}; + +#endif /* HTMLHELP_H */ diff --git a/src/index.cpp b/src/index.cpp index d8bd56c..3ad97d9 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -30,6 +30,7 @@ #include "util.h" #include "groupdef.h" #include "language.h" +#include "htmlhelp.h" //---------------------------------------------------------------------------- @@ -122,7 +123,7 @@ bool hasVisibleRoot(BaseClassList *bcl) for ( ; bcli.current(); ++bcli) { ClassDef *cd=bcli.current()->classDef; - if (cd->isVisibleExt()) return TRUE; + if (cd->isVisibleInHierarchy()) return TRUE; hasVisibleRoot(cd->baseClasses()); } return FALSE; @@ -132,20 +133,27 @@ bool hasVisibleRoot(BaseClassList *bcl) void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper) { + HtmlHelp *htmlHelp=0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp = HtmlHelp::getInstance(); + } BaseClassListIterator bcli(*bcl); bool started=FALSE; for ( ; bcli.current() ; ++bcli) { ClassDef *cd=bcli.current()->classDef; - if (cd->isVisibleExt() && hasVisibleRoot(cd->baseClasses())) + if (cd->isVisibleInHierarchy() && hasVisibleRoot(cd->baseClasses())) { if (!started) { ol.startIndexList(); + if (hasHtmlHelp) htmlHelp->incContentsDepth(); started=TRUE; } //printf("Passed...\n"); - if (cd->hasDocumentation() || cd->isReference()) + if (cd->isLinkable()) { ol.writeIndexItem(cd->getReference(),cd->getOutputFileBase(),cd->name()); if (cd->isReference()) @@ -154,10 +162,19 @@ void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper) ol.docify(" [external]"); ol.endTypewriter(); } + if (hasHtmlHelp) + { + htmlHelp->addContentsItem(cd->name(),cd->getOutputFileBase()); + //cd->writeMembersToContents(); + } } else { ol.writeIndexItem(0,0,cd->name()); + if (hasHtmlHelp) + { + htmlHelp->addContentsItem(cd->name(),"nodoc"); + } } if (!cd->visited && !hideSuper && cd->superClasses()->count()>0) { @@ -166,7 +183,11 @@ void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper) } } } - if (started) ol.endIndexList(); + if (started) + { + ol.endIndexList(); + if (hasHtmlHelp) htmlHelp->decContentsDepth(); + } } //---------------------------------------------------------------------------- @@ -175,6 +196,13 @@ void writeClassHierarchy(OutputList &ol) { initClassHierarchy(&classList); + HtmlHelp *htmlHelp=0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp = HtmlHelp::getInstance(); + } + bool started=FALSE; ClassListIterator cli(classList); for (;cli.current(); ++cli) @@ -182,14 +210,15 @@ void writeClassHierarchy(OutputList &ol) ClassDef *cd=cli.current(); if (!hasVisibleRoot(cd->baseClasses())) { - if (cd->isVisibleExt()) + if (cd->isVisibleInHierarchy()) // WAS: isVisible()! { if (!started) { ol.startIndexList(); + if (hasHtmlHelp) htmlHelp->incContentsDepth(); started=TRUE; } - if (cd->hasDocumentation() || cd->isReference()) + if (cd->isLinkable()) { ol.writeIndexItem(cd->getReference(),cd->getOutputFileBase(),cd->name()); if (cd->isReference()) @@ -198,10 +227,16 @@ void writeClassHierarchy(OutputList &ol) ol.docify(" [external]"); ol.endTypewriter(); } + if (hasHtmlHelp) + { + htmlHelp->addContentsItem(cd->name(),cd->getOutputFileBase()); + //cd->writeMembersToContents(); + } } else { ol.writeIndexItem(0,0,cd->name()); + if (hasHtmlHelp) htmlHelp->addContentsItem(cd->name(),"nodoc"); } } if (!cd->visited && cd->superClasses()->count()>0) @@ -211,11 +246,16 @@ void writeClassHierarchy(OutputList &ol) } } } - if (started) ol.endIndexList(); + if (started) + { + ol.endIndexList(); + if (hasHtmlHelp) htmlHelp->decContentsDepth(); + } } //---------------------------------------------------------------------------- +// TODO: let this function return the real number of items in the hierarchy. int countClassHierarchy() { initClassHierarchy(&classList); @@ -236,8 +276,15 @@ void writeHierarchicalIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"hierarchy","Hierarchical Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trClassHierarchy()); + QCString title = Config::projectName+" "+theTranslator->trClassHierarchy(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"hierarchy"); + } parseText(ol,theTranslator->trClassHierarchyDescription()); ol.newParagraph(); writeClassHierarchy(ol); @@ -258,7 +305,7 @@ int countFiles() FileDef *fd; for (;(fd=fni.current());++fni) { - if (fd->hasDocumentation()) count++; + if (fd->isLinkable()) count++; } } return count; @@ -272,8 +319,17 @@ void writeFileIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"files","File Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trFileList()); + QCString title = Config::projectName+" "+theTranslator->trFileList(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"files"); + htmlHelp->incContentsDepth(); + } ol.newParagraph(); parseText(ol,theTranslator->trFileListDescription(Config::extractAllFlag)); ol.newParagraph(); @@ -285,17 +341,14 @@ void writeFileIndex(OutputList &ol) FileDef *fd=fn->first(); while (fd) { - if (fd->hasDocumentation() && !fd->isReference()) + if (fd->isLinkableInProject()) { //ol.writeIndexItem(fd->getReference(),fd->diskName(), // fd->name()); QCString path; if (Config::fullPathNameFlag) { - path=fd->getPath().copy(); - // strip part of the path - if (path.left(Config::stripFromPath.length())==Config::stripFromPath) - path=path.right(path.length()-Config::stripFromPath.length()); + path=stripFromPath(fd->getPath().copy()); } ol.writeStartAnnoItem("file", @@ -319,12 +372,20 @@ void writeFileIndex(OutputList &ol) } ol.docify(")"); ol.writeEndAnnoItem(fd->name()); + if (hasHtmlHelp) + { + htmlHelp->addContentsItem(fd->name(),fd->getOutputFileBase()); + } } fd=fn->next(); } fn=inputNameList.next(); } ol.endIndexList(); + if (hasHtmlHelp) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Man); } @@ -337,7 +398,7 @@ int countNamespaces() NamespaceDef *nd; for (;(nd=nli.current());++nli) { - if (nd->isVisible()) count++; + if (nd->isLinkableInProject()) count++; } return count; } @@ -350,8 +411,17 @@ void writeNamespaceIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"namespaces","Namespace Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trNamespaceList()); + QCString title = Config::projectName+" "+theTranslator->trNamespaceList(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"namespaces"); + htmlHelp->incContentsDepth(); + } ol.newParagraph(); parseText(ol,theTranslator->trNamespaceListDescription(Config::extractAllFlag)); ol.newParagraph(); @@ -360,7 +430,7 @@ void writeNamespaceIndex(OutputList &ol) NamespaceDef *nd=namespaceList.first(); while (nd) { - if (nd->isVisible()) + if (nd->isLinkableInProject()) { ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name()); ol.docify(" ("); @@ -379,10 +449,18 @@ void writeNamespaceIndex(OutputList &ol) } ol.docify(")"); ol.writeEndAnnoItem(nd->name()); + if (hasHtmlHelp) + { + htmlHelp->addContentsItem(nd->name(),nd->getOutputFileBase()); + } } nd=namespaceList.next(); } ol.endIndexList(); + if (hasHtmlHelp) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Man); } @@ -397,7 +475,7 @@ int countAnnotatedClasses() ClassDef *cd; for (;(cd=cli.current());++cli) { - if (!cd->isReference() && cd->isVisible()) + if (cd->isLinkableInProject()) { //printf("Annotated class %s\n",cd->name().data()); count++; @@ -417,20 +495,15 @@ void writeAnnotatedClassList(OutputList &ol) ClassDef *cd; for (;(cd=cli.current());++cli) { - if (!cd->isReference() && - //!cd->name().isEmpty() && cd->name()[0]!='@' && - //(cd->protection()!=Private || Config::extractPrivateFlag) && - //(cd->hasDocumentation() || !hideClassFlag) - cd->isVisible() - ) + if (cd->isLinkableInProject()) { QCString type; switch (cd->compoundType()) { - case ClassDef::Class: type="class"; break; - case ClassDef::Struct: type="struct"; break; - case ClassDef::Union: type="union"; break; - default: type="unknown"; break; // an error + case ClassDef::Class: type="class"; break; + case ClassDef::Struct: type="struct"; break; + case ClassDef::Union: type="union"; break; + default: type="interface"; break; } ol.writeStartAnnoItem(type,cd->getOutputFileBase(),0,cd->name()); ol.docify(" ("); @@ -449,6 +522,12 @@ void writeAnnotatedClassList(OutputList &ol) } ol.docify(")"); ol.writeEndAnnoItem(cd->name()); + if (Config::generateHtml && Config::htmlHelpFlag) + { + HtmlHelp::getInstance()->addContentsItem( + cd->name(),cd->getOutputFileBase()); + //cd->writeMembersToContents(); + } } cd=classList.next(); } @@ -457,6 +536,50 @@ void writeAnnotatedClassList(OutputList &ol) //---------------------------------------------------------------------------- +void writeAlfabeticalClassList(OutputList &ol) +{ + ol.startAlfabeticalIndexList(); + //ClassDef *cd=classList.first(); + //while (cd) + ClassListIterator cli(classList); + ClassDef *cd; + char startLetter=0; + for (;(cd=cli.current());++cli) + { + if (cd->isLinkableInProject()) + { + if (cd->name().at(0)!=startLetter) + { + startLetter=cd->name().at(0); + char s[2]; s[0]=startLetter; s[1]=0; + ol.writeIndexHeading(s); + } + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(),0,cd->name()); + ol.lineBreak(); + } + cd=classList.next(); + } + ol.endAlfabeticalIndexList(); +} + +//---------------------------------------------------------------------------- + +void writeAlphabeticalIndex(OutputList &ol) +{ + ol.disableAllBut(OutputGenerator::Html); + if (annotatedClasses==0) return; + startFile(ol,"classes.html","Alfabetical index"); + startTitle(ol); + parseText(ol,Config::projectName+" "+theTranslator->trCompoundIndex()); + endTitle(ol,0); + writeAlfabeticalClassList(ol); + endFile(ol); + ol.enableAll(); +} + +//---------------------------------------------------------------------------- + void writeAnnotatedIndex(OutputList &ol) { if (annotatedClasses==0) return; @@ -465,10 +588,23 @@ void writeAnnotatedIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"annotated","Annotated Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trCompoundList()); + QCString title = Config::projectName+" "+theTranslator->trCompoundList(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"annotated"); + htmlHelp->incContentsDepth(); + } parseText(ol,theTranslator->trCompoundListDescription()); writeAnnotatedClassList(ol); + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp->decContentsDepth(); + } + endFile(ol); ol.enable(OutputGenerator::Man); } @@ -487,10 +623,12 @@ void writeMemberList(OutputList &ol) while (md && !found) { ClassDef *cd; - if ((md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && - !md->isReference() && md->hasDocumentation() && - md->name()[0]!='@' && (cd=md->memberClass()) && - cd->isVisible() + if (//(md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && + //!md->isReference() && md->hasDocumentation() && + // md->name()[0]!='@' && + md->isLinkableInProject() && + (cd=md->memberClass()) && + cd->isLinkableInProject() ) { found=TRUE; @@ -511,10 +649,11 @@ void writeMemberList(OutputList &ol) while (md) { ClassDef *cd=md->memberClass(); - if (cd && (md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && - !md->isReference() && md->hasDocumentation() && + if (//cd && (md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && + //!md->isReference() && md->hasDocumentation() && + md->isLinkableInProject() && prevName!=cd->name() && - cd->isVisible() + cd->isLinkableInProject() ) { if (count==0) @@ -548,16 +687,32 @@ int countClassMembers() ClassDef *cd; while (md && !found) { - if ((md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && - !md->isReference() && !md->isRelated() && md->hasDocumentation() && - md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible()) - otherMd=md; - if ((md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && - !md->isReference() && md->isRelated() && md->hasDocumentation() && - md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible()) - found=TRUE; - else - md=mn->next(); + if (//(md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && + //!md->isReference() && !md->isRelated() && md->hasDocumentation() && + //md->name()[0]!='@' && (cd=md->memberClass()) && cd->isLinkable()) + md->isLinkableInProject() && + !md->isRelated() && + (cd=md->memberClass()) && + cd->isLinkableInProject() + ) + { + if (!md->isRelated()) + otherMd=md; + if (md->isRelated()) + found=TRUE; + } + + // otherMd=md; + //if (//(md->isFriend() || md->protection()!=Private || Config::extractPrivateFlag) && + // //!md->isReference() && md->isRelated() && md->hasDocumentation() && + // //md->name()[0]!='@' && (cd=md->memberClass()) && cd->isLinkable() + // md->isLinkableInProject() && + // md->isRelated() && + // (cd=md->memberClass()) && + // cd->isLinkableInProject() + // ) + // found=TRUE; + md=mn->next(); } if (found || otherMd) count++; mn=memberNameList.next(); @@ -597,13 +752,15 @@ void writeFileMemberList(OutputList &ol) { FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec(); bool hasDocs = - (md->getFileDef() && md->getFileDef()->hasDocumentation()) || - (md->getFileDec() && md->getFileDec()->hasDocumentation()); + (md->getFileDef() && md->getFileDef()->isLinkableInProject()) || + (md->getFileDec() && md->getFileDec()->isLinkableInProject()); if (fd && hasDocs && - !md->isReference() && - md->hasDocumentation() && - md->name()[0]!='@') found=TRUE; + md->isLinkableInProject() + //!md->isReference() && + //md->hasDocumentation() && + //md->name()[0]!='@' + ) found=TRUE; else md=mn->next(); } @@ -621,12 +778,13 @@ void writeFileMemberList(OutputList &ol) { FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec(); bool hasDocs = - (md->getFileDef() && md->getFileDef()->hasDocumentation()) || - (md->getFileDec() && md->getFileDec()->hasDocumentation()); + (md->getFileDef() && md->getFileDef()->isLinkableInProject()) || + (md->getFileDec() && md->getFileDec()->isLinkableInProject()); if (fd && hasDocs && - !md->isReference() && - md->hasDocumentation() && - md->name()[0]!='@' && + md->isLinkableInProject() && + //!md->isReference() && + //md->hasDocumentation() && + //md->name()[0]!='@' && prevName!=fd->name()) { if (count==0) @@ -663,9 +821,8 @@ void writeNamespaceMemberList(OutputList &ol) while (md && !found) { NamespaceDef *nd=md->getNamespace(); - if (nd && nd->isVisible() && - !md->isReference() && md->hasDocumentation() && - !md->name().isEmpty() && md->name().at(0)!='@') found=TRUE; + if (nd && nd->isLinkableInProject() && md->isLinkableInProject()) + found=TRUE; else md=mn->next(); } @@ -682,9 +839,7 @@ void writeNamespaceMemberList(OutputList &ol) while (md) { NamespaceDef *nd=md->getNamespace(); - if (nd && nd->isVisible() && - !md->isReference() && md->hasDocumentation() && - !md->name().isEmpty() && md->name().at(0)!='@' && + if (nd && nd->isLinkableInProject() && md->isLinkableInProject() && prevName!=nd->name() ) { @@ -718,10 +873,7 @@ int countNamespaceMembers() while (md && !found) { NamespaceDef *nd=md->getNamespace(); - if (nd && nd->isVisible() && - !md->isReference() && md->hasDocumentation() && - !md->name().isEmpty() && md->name().at(0)!='@' - ) + if (nd && nd->isLinkableInProject() && md->isLinkableInProject()) found=TRUE; else md=mn->next(); @@ -745,11 +897,10 @@ int countFileMembers() bool found=FALSE; while (md && !found) { - if (!md->isReference() && md->hasDocumentation() && - !md->name().isEmpty() && md->name()[0]!='@' && - (((fd=md->getFileDef()) && fd->hasDocumentation()) + if (md->isLinkableInProject() && + (((fd=md->getFileDef()) && fd->isLinkableInProject()) || - ((fd=md->getFileDec()) && fd->hasDocumentation()) + ((fd=md->getFileDec()) && fd->isLinkableInProject()) ) ) found=TRUE; @@ -800,45 +951,79 @@ void writeNamespaceMemberIndex(OutputList &ol) //---------------------------------------------------------------------------- +int countIncludeFiles() +{ + int count=0; + FileDef *fd=includeFiles.first(); + while (fd) + { + if (fd->isLinkableInProject()) + { + count++; + } + fd=includeFiles.next(); + } + return count; +} + void writeHeaderFileList(OutputList &ol) { - if (includeFiles.count()>0) + bool started=FALSE; + FileDef *fd=includeFiles.first(); + while (fd) { - ol.startItemList(); - FileDef *fd=includeFiles.first(); - while (fd) + if (fd->isLinkableInProject()) { + if (!started) + { + started=TRUE; + ol.startItemList(); + } ol.writeListItem(); QCString path; if (Config::fullPathNameFlag) { - path=fd->getPath().copy(); - // strip part of the path - if (path.left(Config::stripFromPath.length())==Config::stripFromPath) - path=path.right(path.length()-Config::stripFromPath.length()); + path=stripFromPath(fd->getPath().copy()); } if (!path.isEmpty()) ol.docify(path); ol.writeObjectLink(0,fd->includeName(),0,fd->name()); ol.writeString("\n"); - fd=includeFiles.next(); - } - ol.endItemList(); - } + if (Config::generateHtml && Config::htmlHelpFlag) + { + HtmlHelp::getInstance()->addContentsItem( + fd->name(),fd->includeName()); + } + } + fd=includeFiles.next(); + } + if (started) ol.endItemList(); } //---------------------------------------------------------------------------- void writeHeaderIndex(OutputList &ol) { - if (includeFiles.count()==0) return; + if (documentedIncludeFiles==0) return; ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Latex); startFile(ol,"headers","Header File Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trHeaderFiles()); + QCString title = Config::projectName+" "+theTranslator->trHeaderFiles(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"headers"); + htmlHelp->incContentsDepth(); + } parseText(ol,theTranslator->trHeaderFilesDescription()); writeHeaderFileList(ol); + if (Config::generateHtml && Config::htmlHelpFlag) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Latex); ol.enable(OutputGenerator::Man); @@ -852,8 +1037,17 @@ void writeExampleIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"examples","Example Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trExamples()); + QCString title = Config::projectName+" "+theTranslator->trExamples(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"examples"); + htmlHelp->incContentsDepth(); + } parseText(ol,theTranslator->trExamplesDescription()); ol.startIndexList(); PageInfo *pi=exampleList.first(); @@ -864,15 +1058,21 @@ void writeExampleIndex(OutputList &ol) if (!pi->title.isEmpty()) { ol.writeObjectLink(0,n,0,pi->title); + if (hasHtmlHelp) htmlHelp->addContentsItem(pi->title,n); } else { ol.writeObjectLink(0,n,0,pi->name); + if (hasHtmlHelp) htmlHelp->addContentsItem(pi->name,n); } ol.writeString("\n"); pi=exampleList.next(); } ol.endIndexList(); + if (hasHtmlHelp) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Man); } @@ -885,8 +1085,17 @@ void writePageIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"pages","Page Index"); startTitle(ol); - ol.docify(Config::projectName+" "+theTranslator->trRelatedPages()); + QCString title = Config::projectName+" "+theTranslator->trRelatedPages(); + ol.docify(title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"pages"); + htmlHelp->incContentsDepth(); + } parseText(ol,theTranslator->trRelatedPagesDescription()); ol.startIndexList(); PageInfo *pi=pageList.first(); @@ -907,9 +1116,14 @@ void writePageIndex(OutputList &ol) ol.writeListItem(); ol.writeObjectLink(0,pageName,0,pageTitle); ol.writeString("\n"); + if (hasHtmlHelp) htmlHelp->addContentsItem(pageTitle,pageName); pi=pageList.next(); } ol.endIndexList(); + if (hasHtmlHelp) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Man); } @@ -960,10 +1174,23 @@ void writeGroupIndex(OutputList &ol) ol.disable(OutputGenerator::Man); startFile(ol,"modules","Module Index"); startTitle(ol); - parseText(ol,Config::projectName+" "+theTranslator->trModules()); + QCString title = Config::projectName+" "+theTranslator->trModules(); + parseText(ol,title); endTitle(ol,0); + HtmlHelp *htmlHelp = 0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) + { + htmlHelp = HtmlHelp::getInstance(); + htmlHelp->addContentsItem(title,"modules"); + htmlHelp->incContentsDepth(); + } parseText(ol,theTranslator->trModulesDescription()); writeGroupList(ol); + if (hasHtmlHelp) + { + htmlHelp->decContentsDepth(); + } endFile(ol); ol.enable(OutputGenerator::Man); } diff --git a/src/index.h b/src/index.h index a472a7a..ad17339 100644 --- a/src/index.h +++ b/src/index.h @@ -43,6 +43,7 @@ class OutputList; void writeIndex(OutputList &ol); void writeHierarchicalIndex(OutputList &ol); +void writeAlphabeticalIndex(OutputList &ol); void writeClassHierarchy(OutputList &ol); void writeFileIndex(OutputList &ol); void writeAnnotatedIndex(OutputList &ol); @@ -66,5 +67,6 @@ int countGroups(); int countNamespaces(); int countAnnotatedClasses(); int countNamespaceMembers(); +int countIncludeFiles(); #endif diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 2f49efa..3834871 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -49,6 +49,7 @@ LatexGenerator::LatexGenerator() { dir=Config::latexOutputDir; col=0; + insideTabbing=FALSE; } LatexGenerator::~LatexGenerator() @@ -196,7 +197,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; while (gd && !found) { - if (gd->hasDocumentation() || gd->countMembers()>0) + if (gd->isLinkableInProject() || gd->countMembers()>0) { if (Config::compactLatexFlag) t << "\\section"; else t << "\\chapter"; t << "{"; //Module Documentation}\n"; @@ -212,7 +213,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->hasDocumentation()) + if (nd->isLinkableInProject()) { if (Config::compactLatexFlag) t << "\\section"; else t << "\\chapter"; t << "{"; // Namespace Documentation}\n": @@ -228,7 +229,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; while (cd && !found) { - if (!cd->isReference() && cd->isVisible()) + if (cd->isLinkableInProject()) { if (Config::compactLatexFlag) t << "\\section"; else t << "\\chapter"; t << "{"; //Compound Documentation}\n"; @@ -247,7 +248,7 @@ void LatexGenerator::startIndexSection(IndexSections is) FileDef *fd=fn->first(); while (fd) { - if (fd->hasDocumentation() && !fd->isReference()) + if (fd->isLinkableInProject()) { if (isFirst) { @@ -317,7 +318,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; while (gd && !found) { - if (gd->hasDocumentation() || gd->countMembers()>0) + if (gd->isLinkableInProject() || gd->countMembers()>0) { t << "}\n\\input{" << gd->getOutputFileBase() << "}\n"; found=TRUE; @@ -326,7 +327,7 @@ void LatexGenerator::endIndexSection(IndexSections is) } while (gd) { - if (gd->hasDocumentation() || gd->countMembers()>0) + if (gd->isLinkableInProject() || gd->countMembers()>0) { if (Config::compactLatexFlag) t << "\\input"; else t << "\\include"; t << "{" << gd->getOutputFileBase() << "}\n"; @@ -341,7 +342,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->hasDocumentation() || nd->countMembers()>0) + if (nd->isLinkableInProject() || nd->countMembers()>0) { t << "}\n\\input{" << nd->getOutputFileBase() << "}\n"; found=TRUE; @@ -350,7 +351,7 @@ void LatexGenerator::endIndexSection(IndexSections is) } while (nd) { - if (nd->hasDocumentation() || nd->countMembers()>0) + if (nd->isLinkableInProject() || nd->countMembers()>0) { if (Config::compactLatexFlag) t << "\\input"; else t << "\\include"; t << "{" << nd->getOutputFileBase() << "}\n"; @@ -365,11 +366,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; while (cd && !found) { - //if (cd->classFile()[0]!='@' && !cd->getReference() && - // (cd->hasDocumentation() || !hideClassFlag) && - // (cd->protection()!=Private || extractPrivateFlag) - // ) - if (!cd->isReference() && cd->isVisible()) + if (cd->isLinkableInProject()) { t << "}\n\\input{" << cd->getOutputFileBase() << "}\n"; found=TRUE; @@ -378,11 +375,7 @@ void LatexGenerator::endIndexSection(IndexSections is) } while (cd) { - //if (cd->classFile()[0]!='@' && !cd->getReference() && - // (cd->hasDocumentation() || !hideClassFlag) && - // (cd->protection()!=Private || extractPrivateFlag) - // ) - if (!cd->isReference() && cd->isVisible()) + if (cd->isLinkableInProject()) { if (Config::compactLatexFlag) t << "\\input"; else t << "\\include"; t << "{" << cd->getOutputFileBase() << "}\n"; @@ -400,7 +393,7 @@ void LatexGenerator::endIndexSection(IndexSections is) FileDef *fd=fn->first(); while (fd) { - if (fd->hasDocumentation() && !fd->isReference()) + if (fd->isLinkableInProject()) { if (isFirst) { @@ -791,13 +784,18 @@ void LatexGenerator::docify(const char *str) case '^': t << "$^\\wedge$"; break; case '&': t << "\\&"; break; case '*': t << "$\\ast$"; break; - case '_': t << "\\_\\-"; break; + case '_': t << "\\_"; + if (!insideTabbing) t << "\\-"; + break; case '{': t << "\\{"; break; case '}': t << "\\}"; break; case '<': t << "$<$"; break; case '>': t << "$>$"; break; case '|': t << "$|$"; break; case '~': t << "$\\sim$"; break; + case ']': if (pc=='[') t << "$\\,$"; + t << "]"; + break; case '-': if (*p=='>') { t << " $\\rightarrow$ "; p++; } else @@ -824,7 +822,7 @@ void LatexGenerator::docify(const char *str) } else // ascii char => see if we can insert hypenation hint { - if (isupper(c) && islower(pc)) t << "\\-"; + if (isupper(c) && islower(pc) && !insideTabbing) t << "\\-"; t << (char)c; } } @@ -900,7 +898,7 @@ void LatexGenerator::docify(const char *str) default: // normal ascii char { // see if we can insert an hyphenation hint - if (isupper(c) && islower(pc)) t << "\\-"; + if (isupper(c) && islower(pc) && !insideTabbing) t << "\\-"; t << (char)c; } } @@ -955,3 +953,56 @@ void LatexGenerator::writeFormula(const char *,const char *text) { t << text; } + +void LatexGenerator::startMemberItem(bool,int annType) +{ + if (!insideTabbing) + { + t << "\\item " << endl; + switch(annType) + { + case 0: break; + case 1: + default: + t << "\\begin{tabbing}" << endl; + t << "xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=\\kill" << endl; + insideTabbing=TRUE; + break; + } + } +} + +void LatexGenerator::endMemberItem(bool,const char *,const char *,bool endItem) +{ + if (endItem) + { + t << endl << "\\end{tabbing}"; + insideTabbing=FALSE; + } + if (insideTabbing) + { + t << "\\\\"; + } + t << endl; +} + +void LatexGenerator::writeNonBreakableSpace() +{ + if (insideTabbing) + t << "\\>"; + else + t << "\\ "; +} + +void LatexGenerator::startMemberList() +{ + if (!insideTabbing) + t << "\\begin{CompactItemize}" << endl; +} + +void LatexGenerator::endMemberList() +{ + if (!insideTabbing) + t << "\\end{CompactItemize}" << endl; +} + diff --git a/src/latexgen.h b/src/latexgen.h index cfd8230..06f8ea8 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -63,6 +63,9 @@ class LatexGenerator : public OutputGenerator void endItemList() { t << "\\end{CompactItemize}" << endl; } void startEnumList() { t << "\\begin{enumerate}" << endl; } void endEnumList() { t << "\\end{enumerate}" << endl; } + void startAlfabeticalIndexList() {} + void endAlfabeticalIndexList() {} + void writeIndexHeading(const char *) {} void writeIndexItem(const char *ref,const char *file,const char *name); void docify(const char *text); void codify(const char *text); @@ -85,10 +88,12 @@ class LatexGenerator : public OutputGenerator void endMemberHeader() { endGroupHeader(); } void startMemberSubtitle() {} void endMemberSubtitle() {} - void startMemberList() { t << "\\begin{CompactItemize}" << endl; } - void endMemberList() { t << "\\end{CompactItemize}" << endl; } - void startMemberItem() { t << "\\item " << endl; } - void endMemberItem() { t << endl; } + void startMemberList(); + void endMemberList(); + void startMemberItem(bool,int); + void endMemberItem(bool,const char *,const char *,bool); + void memberGroupSpacing(bool) {} + void memberGroupSeparator() {} void insertMemberAlign() {} void writeRuler() { t << "\\vspace{0.4cm}\\hrule\\vspace{0.2cm}"; } @@ -173,6 +178,7 @@ class LatexGenerator : public OutputGenerator void startQuickIndexItem(const char *,const char *) {} void endQuickIndexItem() {} void writeFormula(const char *,const char *); + void writeNonBreakableSpace(); //static void docifyStatic(QTextStream &t,const char *str); @@ -180,6 +186,7 @@ class LatexGenerator : public OutputGenerator LatexGenerator(const LatexGenerator &); LatexGenerator &operator=(const LatexGenerator &); int col; + bool insideTabbing; }; #endif diff --git a/src/logos.cpp b/src/logos.cpp index ac6e782..dbc47ff 100644 --- a/src/logos.cpp +++ b/src/logos.cpp @@ -19,6 +19,15 @@ #include "qtbc.h" #include <qfile.h> + +unsigned char null_data[] = { + 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0xff, + 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x02, 0x02, 0x44, 0x01, 0x00, 0x3b +}; +unsigned int null_len = 43; + unsigned char logo_data[] = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x76, 0x00, 0x35, 0x00, 0xf7, 0x00, 0x00, 0x31, 0x7b, 0x6b, 0x31, 0x7b, 0x73, 0x31, 0x84, 0x7b, 0x31, 0x84, @@ -490,6 +499,18 @@ unsigned char search_data[] = { }; unsigned int search_len = 2010; +void writeNullImage(const char *dir) +{ + QCString fileName=(QCString)dir+"/null.gif"; + QFile f(fileName); + if (f.open(IO_WriteOnly)) + f.writeBlock((char *)null_data,null_len); + else + { + fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data()); + } + f.close(); +} void writeLogo(const char *dir) { diff --git a/src/logos.h b/src/logos.h index 1054fdb..dc2ec51 100644 --- a/src/logos.h +++ b/src/logos.h @@ -18,6 +18,7 @@ #define LOGOS_H extern void writeLogo(const char *dir); +extern void writeNullImage(const char *dir); extern void writeSearchButton(const char *dir); #endif diff --git a/src/mangen.cpp b/src/mangen.cpp index 056bc90..963460b 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -31,6 +31,7 @@ ManGenerator::ManGenerator() : OutputGenerator() paragraph=FALSE; col=0; upperCase=FALSE; + insideTabbing=FALSE; } ManGenerator::~ManGenerator() @@ -342,3 +343,38 @@ void ManGenerator::endDescItem() t << "\" 1c" << endl; firstCol=TRUE; } + +void ManGenerator::startMemberItem(bool,int annType) +{ + if (firstCol && !insideTabbing) t << ".in +1c\n"; + t << "\n.ti -1c\n.RI \""; + firstCol=FALSE; + if (annType!=0) insideTabbing=TRUE; +} + +void ManGenerator::endMemberItem(bool,const char *,const char *,bool endItem) +{ + if (endItem) + { + insideTabbing=FALSE; + t << "\"\n.br\n.RI \""; + } + t << "\"\n.br"; +} + +void ManGenerator::startMemberList() +{ + if (!insideTabbing) + { + t << "\n.in +1c"; firstCol=FALSE; + } +} + +void ManGenerator::endMemberList() +{ + if (!insideTabbing) + { + t << "\n.in -1c"; firstCol=FALSE; + } +} + diff --git a/src/mangen.h b/src/mangen.h index 03a6a39..0df3268 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -63,6 +63,9 @@ class ManGenerator : public OutputGenerator void endItemList() {} void startEnumList() {} void endEnumList() {} + void startAlfabeticalIndexList() {} + void endAlfabeticalIndexList() {} + void writeIndexHeading(const char *) {} void writeIndexItem(const char *ref,const char *file,const char *name); void docify(const char *text); void codify(const char *text); @@ -85,13 +88,12 @@ class ManGenerator : public OutputGenerator void startMemberSubtitle() {} void endMemberSubtitle() {} void writeListItem(); - void startMemberList() { t << "\n.in +1c"; firstCol=FALSE; } - void endMemberList() { t << "\n.in -1c"; firstCol=FALSE; } - void startMemberItem() { if (firstCol) t << ".in +1c"; - t << "\n.ti -1c\n.RI \""; - firstCol=FALSE; - } - void endMemberItem() { t << "\"\n.br"; } + void startMemberList(); + void endMemberList(); + void startMemberItem(bool,int); + void endMemberItem(bool,const char *,const char *,bool); + void memberGroupSpacing(bool) {} + void memberGroupSeparator() {} void writeRuler() {} void writeAnchor(const char *) {} void startCodeFragment(); @@ -164,12 +166,14 @@ class ManGenerator : public OutputGenerator void startQuickIndexItem(const char *,const char *) {} void endQuickIndexItem() {} void writeFormula(const char *,const char *) {} + void writeNonBreakableSpace() { t << " "; } private: bool firstCol; bool paragraph; int col; bool upperCase; + bool insideTabbing; ManGenerator(const ManGenerator &g); ManGenerator &operator=(const ManGenerator &g); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 1321692..34061f0 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -21,6 +21,165 @@ #include "doxygen.h" #include "util.h" #include "message.h" +#include "htmlhelp.h" +#include "language.h" + +//----------------------------------------------------------------------------- + +static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t) +{ + QCString result; + QCString clRealName=n; + int p=0,i; + if ((i=clRealName.find('<'))!=-1) + { + clRealName=clRealName.left(i); // strip template specialization + } + if ((i=clRealName.findRev("::"))!=-1) + { + clRealName=clRealName.right(clRealName.length()-i-2); + } + while ((i=s.find(clRealName,p))!=-1) + { + result+=s.mid(p,i-p); + uint j=clRealName.length()+i; + if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j)))) + { // add template names + //printf("Adding %s+%s\n",clRealName.data(),t.data()); + result+=clRealName+t; + } + else + { // template names already present + //printf("Adding %s\n",clRealName.data()); + result+=clRealName; + } + p=i+clRealName.length(); + } + result+=s.right(s.length()-p); + //printf("addTemplateNames(%s,%s,%s)=%s\n",s.data(),n.data(),t.data(),result.data()); + return result; +} + +static void writeDefArgumentList(OutputList &ol,ClassDef *cd, + const QCString &scopeName,MemberDef *md) +{ + ArgumentList *argList=md->argumentList(); + if (argList==0) return; // member has no function like argument list + ol.docify(" ("); // start argument list + Argument *a=argList->first(); + QCString cName; + if (md->scopeDefTemplateArguments()) + { + cName=tempArgListToString(md->scopeDefTemplateArguments()); + } + if (cd) + { + cName=cd->name(); + int il=cName.find('<'); + int ir=cName.findRev('>'); + if (il!=-1 && ir!=-1 && ir>il) + { + cName=cName.mid(il,ir-il+1); + //printf("1. cName=%s\n",cName.data()); + } + else if (cd->templateArguments()) + { + cName=tempArgListToString(cd->templateArguments()); + //printf("2. cName=%s\n",cName.data()); + } + else // no template specifier + { + cName.resize(0); + } + } + //printf("~~~ %s cName=%s\n",md->name().data(),cName.data()); + while (a) + { + QRegExp re(")("); + int vp; + if (!a->attrib.isEmpty()) + { + ol.docify(a->attrib+" "); + } + if ((vp=a->type.find(re))!=-1) // argument type is a function pointer + { + QCString n=a->type.left(vp); + if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); + linkifyText(ol,scopeName,md->name(),n); + } + else // non-function pointer type + { + QCString n=a->type; + if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); + linkifyText(ol,scopeName,md->name(),n); + } + if (a->name.length()>0) // argument has a name + { + ol.docify(" "); + ol.disable(OutputGenerator::Man); + ol.startEmphasis(); + ol.enable(OutputGenerator::Man); + ol.docify(a->name); + ol.disable(OutputGenerator::Man); + ol.endEmphasis(); + ol.enable(OutputGenerator::Man); + } + if (vp!=-1) // write the part of the argument type + // that comes after the name + { + linkifyText(ol,scopeName,md->name(),a->type.right(a->type.length()-vp)); + } + if (a->defval.length()>0) // write the default value + { + QCString n=a->defval; + if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); + ol.docify(" = "); + linkifyText(ol,scopeName,md->name(),n); + } + a=argList->next(); + if (a) ol.docify(", "); // there are more arguments + } + ol.docify(")"); // end argument list + if (argList->constSpecifier) + { + ol.docify(" const"); + } + if (argList->volatileSpecifier) + { + ol.docify(" volatile"); + } +} + +static void writeTemplatePrefix(OutputList &ol,ArgumentList *al,bool br=TRUE) +{ + ol.docify("template<"); + Argument *a=al->first(); + while (a) + { + ol.docify(a->type); + ol.docify(a->name); + if (a->defval.length()!=0) + { + ol.docify(" = "); + ol.docify(a->defval); + } + a=al->next(); + if (a) ol.docify(", "); + } + ol.docify("> "); + if (br) + { + bool latexEnabled = ol.isEnabled(OutputGenerator::Latex); + bool manEnabled = ol.isEnabled(OutputGenerator::Man); + if (latexEnabled) ol.disable(OutputGenerator::Latex); + if (manEnabled) ol.disable(OutputGenerator::Man); + ol.lineBreak(); + if (latexEnabled) ol.enable(OutputGenerator::Latex); + if (manEnabled) ol.enable(OutputGenerator::Man); + } +} + +//----------------------------------------------------------------------------- /*! Creates a new member definition. * Members can be function/variables/enums/etc. inside a class or inside a @@ -59,11 +218,14 @@ MemberDef::MemberDef(const char *t,const char *na,const char *a,const char *e, enumScope=0; enumDeclList=0; scopeTAL=0; + membTAL=0; type=substituteClassNames(t); args=substituteClassNames(a); if (type.isNull()) decl=name()+args; else decl=type+" "+name()+args; declLine=0; defLine=0; + grpId=-1; + memberGroup=0; virt=v; prot=p; related=r; @@ -72,6 +234,10 @@ MemberDef::MemberDef(const char *t,const char *na,const char *a,const char *e, exception=e; eUsed=FALSE; proto=FALSE; + annScope=FALSE; + annMemb=0; + annUsed=FALSE; + indDepth=0; docEnumValues=FALSE; // copy function template arguments (if any) if (tal) @@ -203,49 +369,767 @@ QCString MemberDef::getOutputFileBase() const return "dummy"; } -void MemberDef::setScopeTemplateArguments(ArgumentList *tal) +static void copyArgumentList(const ArgumentList *src,ArgumentList *dst) +{ + ArgumentListIterator tali(*src); + Argument *a; + for (;(a=tali.current());++tali) + { + dst->append(new Argument(*a)); + } + dst->constSpecifier = src->constSpecifier; + dst->volatileSpecifier = src->volatileSpecifier; + dst->pureSpecifier = src->pureSpecifier; +} + +void MemberDef::setScopeDefTemplateArguments(ArgumentList *tal) { // copy function arguments (if any) if (tal) { scopeTAL = new ArgumentList; scopeTAL->setAutoDelete(TRUE); - ArgumentListIterator tali(*tal); - Argument *a; - for (;(a=tali.current());++tali) + copyArgumentList(tal,scopeTAL); + } +} + +void MemberDef::setMemberDefTemplateArguments(ArgumentList *tal) +{ + // copy function arguments (if any) + if (tal) + { + membTAL = new ArgumentList; + membTAL->setAutoDelete(TRUE); + copyArgumentList(tal,membTAL); + } +} + + + +void MemberDef::setGroupId(int groupId) +{ + grpId=groupId; + if (grpId!=-1) + { + memberGroup=memberGroupDict[grpId]; + memberGroup->insertMember(this); + } +} + +void MemberDef::writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd, + FileDef *fd,MemberGroup *mg) +{ + if (mg) + ol.writeObjectLink(0,mg->getOutputFileBase(), + anchor(),name()); + else if (nd) + ol.writeObjectLink(nd->getReference(),nd->getOutputFileBase(), + anchor(),name()); + else if (fd) + ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(), + anchor(),name()); + else + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(), + anchor(),name()); +} + +void MemberDef::writeDeclaration(OutputList &ol,ClassDef *cd,NamespaceDef *nd,FileDef *fd, + int prevGroupId,bool inGroup) +{ + int i,l; + bool hasDocs=hasDocumentation(); + //if (cd) printf("MemberDef: %s in class %s annScope=%d annMemb=%p\n", + // name().data(),cd->name().data(),annScope,annMemb); + if (annScope) return; + if (!hasDocs && Config::hideMemberFlag) return; + if (Config::hideMemberFlag && documentation().isEmpty() && + !Config::briefMemDescFlag && !Config::repeatBriefFlag + ) return; + QCString type=typeString(); + // strip `static' keyword from type + if (type.left(7)=="static ") type=type.right(type.length()-7); + // strip `friend' keyword from type + if (type.left(7)=="friend ") type=type.right(type.length()-7); + QRegExp r("@[0-9]+"); + if ((i=r.match(type,0,&l))==-1 || !enumUsed()) + { + + if (Config::genTagFile.length()>0) + { + tagFile << name() << " " << anchor() << " \"" + << argsString() << "\"\n"; + } + + Definition *d=0; + if (cd) d=cd; else if (nd) d=nd; else d=fd; + QCString cname = d->name(); + QCString cfname = d->getOutputFileBase(); + + int gId = inGroup ? -1 : groupId(); + MemberGroup *mg = (gId!=prevGroupId && gId!=-1) ? memberGroupDict[gId] : 0; + const char *gHeader = 0; + const char *gFile = 0; + if (mg) + { + gHeader=mg->header(); + gFile=mg->getOutputFileBase(); + } + + if (!inGroup) + { + if (prevGroupId==-1 && gId!=-1) + { + ol.memberGroupSpacing(FALSE); + ol.memberGroupSeparator(); + } + else if (prevGroupId!=-1 && gId==-1) + { + ol.memberGroupSpacing(TRUE); + ol.memberGroupSeparator(); + } + else if (prevGroupId!=-1 && gId!=-1 && prevGroupId!=gId) + { + ol.memberGroupSpacing(TRUE); + ol.memberGroupSeparator(); + } + } + + HtmlHelp *htmlHelp=0; + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance(); + + // search for the last annonymous scope in the member type + ClassDef *annoClassDef=0; + while (i!=-1 && cname.find(type.mid(i,l))!=-1) + { + i=r.match(type,i+l,&l); + } + if (i!=-1) + { + // get the definition of the annonymous class that is + // the type of this member + annoClassDef=getClass(cname+"::"+type.mid(i,l)); + } + + // start a new member declaration + ol.startMemberItem(gId!=-1,((i!=-1) || annMemb) ? 1 : 0); + + // If there is no detailed description we need to write the anchor here. + bool detailsVisible = detailsAreVisible(); + if (!detailsVisible && !Config::extractAllFlag && !annMemb) + { + QCString doxyName=name().copy(); + if (!cname.isEmpty()) doxyName.prepend(cname+"::"); + ol.writeDoxyAnchor(cname,anchor(),doxyName); + ol.addToIndex(name(),cname); + ol.addToIndex(cname,name()); + if (hasHtmlHelp) + { + htmlHelp->addIndexItem(cname,name(),cfname,anchor()); + } + ol.docify("\n"); + } + //else if (!detailsVisible) // when extractAll it true we have to write + // // a index reference and label in LaTeX because + // // detailed section not shown in LaTeX + //{ + // ol.addToIndex(name(),cname); + // ol.addToIndex(cname,name()); + // ol.writeLatexLabel(cname,anchor()); + //} + + if (tArgList) + { + writeTemplatePrefix(ol,tArgList,FALSE); + } + + if (i!=-1 || annMemb) + { + int j; + for (j=0;j<indDepth;j++) + { + ol.writeNonBreakableSpace(); + } + } + + if (i!=-1) + { + //printf("scopeName=`%s' annonymous=`%s'\n", + // cname.data(),type.mid(i,l).data()); + + if (annoClassDef) + { + //printf("class found!\n"); + annoClassDef->writeDeclaration(ol); + ol.startMemberItem(gId!=-1,2); + int j; + for (j=0;j<indDepth;j++) + { + ol.writeNonBreakableSpace(); + } + ol.docify("}"); + ol.docify(type.right(type.length()-i-l).stripWhiteSpace()); + } + else + { + type = type.left(i) + " { ... } " + type.right(type.length()-i-l); + linkifyText(ol,cname,name(),type); + } + } + else + { + linkifyText(ol,cname,name(),type); + } + bool htmlOn = ol.isEnabled(OutputGenerator::Html); + if (htmlOn && Config::htmlAlignMemberFlag && type.length()>0) + { + ol.disable(OutputGenerator::Html); + } + if (!type.isEmpty()) ol.docify(" "); + if (htmlOn) + { + ol.enable(OutputGenerator::Html); + } + + if (annMemb) + { + bool latexOn = ol.isEnabled(OutputGenerator::Latex); + bool manOn = ol.isEnabled(OutputGenerator::Latex); + if (latexOn) ol.disable(OutputGenerator::Latex); + if (manOn) ol.disable(OutputGenerator::Man); + ol.writeNonBreakableSpace(); + if (latexOn) ol.enable(OutputGenerator::Latex); + if (manOn) ol.enable(OutputGenerator::Man); + } + else + ol.insertMemberAlign(); + + // write name + if (grpId!=-1) + { + if (annMemb) + { + //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor()); + annMemb->writeLink(ol,cd,nd,fd,inGroup ? memberGroup : 0); + annMemb->annUsed=annUsed=TRUE; + } + else + writeLink(ol,0,0,0,memberGroup); + //ol.writeBoldString(name()); + } + else if (isLinkable()) + { + if (annMemb) + { + //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor()); + annMemb->writeLink(ol,annMemb->memberClass(),nd,fd,inGroup ? memberGroup : 0); + annMemb->annUsed=annUsed=TRUE; + } + else + //printf("writeLink %s->%d\n",name.data(),hasDocumentation()); + writeLink(ol,cd,nd,fd,inGroup ? memberGroup : 0); + } + else // there is a brief member description and brief member + // descriptions are enabled or there is no detailed description. { - scopeTAL->append(new Argument(*a)); + if (annMemb) annMemb->annUsed=annUsed=TRUE; + ol.writeBoldString(name()); + } + + // if member template specifiers are not part of the name, but they are + // present, we add them + if (tArgList && !(name().find('<')!=-1 && name().find('>')!=-1) + && cd && cd->templateArguments()) + { + ol.docify(tempArgListToString(tArgList)); + } + + if (argsString()) + { + ol.writeString(" "); + //ol.docify(argsString()); + linkifyText(ol,cname,name(),argsString()); + } + + if (excpString()) + { + ol.writeString(" "); + ol.docify(excpString()); + } + + ol.endMemberItem(gId!=-1,gFile,gHeader,annoClassDef!=0 && indDepth==0); + + // write brief description + if (!briefDescription().isEmpty() && Config::briefMemDescFlag && + gId==-1 && !inGroup && !annMemb) + { + ol.startMemberDescription(); + parseDoc(ol,cname,name(),briefDescription()); + if (!documentation().isEmpty()) + { + ol.disableAllBut(OutputGenerator::Html); + ol.endEmphasis(); + ol.docify(" "); + ol.startTextLink(0,anchor()); + parseText(ol,theTranslator->trMore()); + ol.endTextLink(); + ol.startEmphasis(); + ol.enableAll(); + } + ol.endMemberDescription(); + ol.newParagraph(); } - scopeTAL->constSpecifier = tal->constSpecifier; - scopeTAL->volatileSpecifier = tal->volatileSpecifier; - scopeTAL->pureSpecifier = tal->pureSpecifier; } + warnIfUndocumented(); } -QCString MemberDef::getScopeTemplateNameString() + +void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,const char *scopeName, + MemberType m) { - QCString result; - if (!scopeTAL || scopeTAL->count()==0) return result; - result="<"; - Argument *a=scopeTAL->first(); - while (a) + bool hasDocs = detailsAreVisible(); + if ( + (memberType()==m && // filter member type + (Config::extractAllFlag || hasDocs) && + groupId()==-1 + ) || /* member is part of an annonymous scope that is the type of + * another member in the list. + */ + (!hasDocs && !briefDescription().isEmpty() && annUsed) + ) { - if (a->name.length()>0) // add template argument name + //printf("************* Writing docs for member %s\n",name().data()); + //if (Config::extractAllFlag && !hasDocs) + //{ + // ol.disable(OutputGenerator::Latex); // Latex cannot insert a pagebreak + // // if there are a lot of empty sections, + // // so we disable LaTeX for all empty + // // sections even if Config::extractAllFlag is enabled + //} + NamespaceDef *nd=getNamespace(); + ClassDef *cd=memberClass(); + FileDef *fd=getFileDef(); + Definition *d = 0; + if (cd) d=cd; else if (nd) d=nd; else d=fd; + QCString cname = d->name(); + QCString cfname = d->getOutputFileBase(); + + // get member name + QCString doxyName=name().copy(); + // prepend scope if there is any + if (scopeName) doxyName.prepend((QCString)scopeName+"::"); + + QCString def = definition(); + if (isEnumerate()) def.prepend("enum "); + MemberDef *smd; + if (isEnumValue() && def[0]=='@') def = def.right(def.length()-2); + int i=0,l,dummy; + QRegExp r("@[0-9]+"); + if (isEnumerate() && r.match(def,0,&l)!=-1) return; + if (isEnumValue() && (smd = getEnumScope()) + && r.match(smd->name(),0,&dummy)==-1) return; + + bool hasHtmlHelp = Config::generateHtml && Config::htmlHelpFlag; + HtmlHelp *htmlHelp = 0; + if (hasHtmlHelp) htmlHelp = HtmlHelp::getInstance(); + + if ((isVariable() || isTypedef()) && (i=r.match(def,0,&l))!=-1) { - result+=a->name; + // find enum type an insert it in the definition + MemberListIterator vmli(*ml); + MemberDef *vmd; + bool found=FALSE; + for ( ; (vmd=vmli.current()) && !found ; ++vmli) + { + if (vmd->isEnumerate() && def.mid(i,l)==vmd->name()) + { + ol.startMemberDoc(cname,name(),anchor()); + if (hasHtmlHelp) + { + htmlHelp->addIndexItem(cname,name(),cfname,anchor()); + } + ol.writeDoxyAnchor(cname,anchor(),doxyName); + linkifyText(ol,scopeName,name(),def.left(i)); + ol+=*vmd->enumDecl(); + linkifyText(ol,scopeName,name(),def.right(def.length()-i-l)); + found=TRUE; + } + } + if (!found) // anonymous compound + { + //printf("Annonymous compound `%s'\n",cname.data()); + ol.startMemberDoc(cname,name(),anchor()); + if (hasHtmlHelp) + { + htmlHelp->addIndexItem(cname,name(),cfname,anchor()); + } + ol.writeDoxyAnchor(cname,anchor(),doxyName); + // strip annonymous compound names from definition + int si=def.find(' '),pi,ei=i+l; + if (si==-1) si=0; + while ((pi=r.match(def,i+l,&l))!=-1) ei=i=pi+l; + // first si characters of def contain compound type name + ol.docify(def.left(si)); + ol.docify(" { ... } "); + // last ei characters of def contain pointer/reference specifiers + linkifyText(ol,scopeName,name(),def.right(def.length()-ei)); + } } - else // extract name from type + else { - int i=a->type.length()-1; - while (i>=0 && isId(a->type.at(i))) i--; - if (i>0) + ol.startMemberDoc(cname,name(),anchor()); + if (hasHtmlHelp) + { + htmlHelp->addIndexItem(cname,name(),cfname,anchor()); + } + ol.writeDoxyAnchor(cname,anchor(),doxyName); + + ArgumentList *scopeAl=scopeDefTemplateArguments(); + if (scopeAl==0 && cd) scopeAl=cd->templateArguments(); + + ArgumentList *membAl=memberDefTemplateArguments(); + if (membAl==0) membAl=templateArguments(); + + //if (cd && (!isRelated() || templateArguments()!=0) && + // ((al=scopeDefTemplateArguments()) || (al=cd->templateArguments())) + // ) + if (scopeAl) // class template prefix + { + writeTemplatePrefix(ol,scopeAl); + } + if (scopeAl && membAl) ol.docify(" "); + + if (membAl) // function template prefix { - result+=a->type.right(a->type.length()-i-1); + writeTemplatePrefix(ol,membAl); } + if (cd) + { + QCString cName=cd->name(); + //printf("cName=%s\n",cName.data()); + int il=cName.find('<'); + int ir=cName.findRev('>'); + if (il!=-1 && ir!=-1 && ir>il) + { + def=addTemplateNames(def, + cName.left(il), /* class without template spec */ + cName.mid(il,ir-il+1) /* templ spec */ + ); + } + else if (scopeAl) + { + def=addTemplateNames(def,cName,tempArgListToString(scopeAl)); + } + } + linkifyText(ol,scopeName,name(),def); + writeDefArgumentList(ol,cd,scopeName,this); + if (excpString()) + { + ol.docify(" "); + linkifyText(ol,scopeName,name(),excpString()); + } + } + + Specifier virt=virtualness(); + MemberDef *rmd=reimplements(); + while (rmd && virt==Normal) + { + virt = rmd->virtualness()==Normal ? Normal : Virtual; + rmd = rmd->reimplements(); + } + + if (isStatic() || protection()!=Public || + virt!=Normal || isSignal() || isFriend() || + isRelated() || isSlot() + ) + { + // write the member specifier list + ol.writeLatexSpacing(); + ol.startTypewriter(); + ol.docify(" ["); + QStrList sl; + if (isFriend()) sl.append("friend"); + else if (isRelated()) sl.append("related"); + else + { + if (isStatic()) sl.append("static"); + if (protection()==Protected) sl.append("protected"); + else if (protection()==Private) sl.append("private"); + if (virt==Virtual) sl.append("virtual"); + else if (virt==Pure) sl.append("pure virtual"); + if (isSignal()) sl.append("signal"); + if (isSlot()) sl.append("slot"); + } + const char *s=sl.first(); + while (s) + { + ol.docify(s); + s=sl.next(); + if (s) ol.docify(", "); + } + ol.docify("]"); + ol.endTypewriter(); + } + ol.endMemberDoc(); + ol.startIndent(); + ol.newParagraph(); + + if (!briefDescription().isEmpty() && + (Config::repeatBriefFlag || + (!Config::briefMemDescFlag && documentation().isEmpty()) + ) || !annMemb + ) + { + parseDoc(ol,scopeName,name(),briefDescription()); + ol.newParagraph(); + } + if (!documentation().isEmpty()) + { + parseDoc(ol,scopeName,name(),documentation()+"\n"); + } + if (!bodyCode().isEmpty()) + { + ol.startCodeFragment(); + parseCode(ol,scopeName,bodyCode(),FALSE,0); + ol.endCodeFragment(); + } + + if (isEnumerate()) + { + bool first=TRUE; + MemberList *fmdl=enumFieldList(); + if (fmdl) + { + MemberDef *fmd=fmdl->first(); + while (fmd) + { + if (fmd->isLinkable()) + { + if (first) + { + ol.newParagraph(); + ol.startBold(); + parseText(ol,theTranslator->trEnumerationValues()); + //ol.writeBoldString("Enumeration values:"); + ol.docify(":"); + ol.endBold(); + ol.startItemList(); + } + ol.writeDoxyAnchor(cname,fmd->anchor(),fmd->name()); + ol.addToIndex(fmd->name(),cname); + ol.addToIndex(cname,fmd->name()); + if (Config::generateHtml && Config::htmlHelpFlag) + { + HtmlHelp::getInstance()->addIndexItem(cname,fmd->name(),cfname,fmd->anchor()); + } + ol.writeListItem(); + first=FALSE; + ol.startBold(); + ol.docify(fmd->name()); + ol.endBold(); + ol.newParagraph(); + + if (!fmd->briefDescription().isEmpty()) + { + parseDoc(ol,scopeName,fmd->name(),fmd->briefDescription()); + ol.newParagraph(); + } + if (!fmd->documentation().isEmpty()) + { + parseDoc(ol,scopeName,fmd->name(),fmd->documentation()+"\n"); + } + ol.disable(OutputGenerator::Man); + ol.newParagraph(); + ol.enable(OutputGenerator::Man); + } + fmd=fmdl->next(); + } + } + if (!first) { ol.endItemList(); ol.writeChar('\n'); } + } + + MemberDef *bmd=reimplements(); + ClassDef *bcd=0; + if (bmd && (bcd=bmd->memberClass())) + { + if (virt!=Normal) // search for virtual member of the deepest base class + { + MemberDef *lastBmd=bmd; + while (lastBmd) + { + ClassDef *lastBcd = lastBmd->memberClass(); + if (lastBmd->virtualness()!=Normal && + lastBmd->isLinkable() && + lastBcd->isLinkable() + ) { bmd=lastBmd; bcd=lastBcd; } + lastBmd=lastBmd->reimplements(); + } + } + // write class that contains a member that is reimplemented by this one + if (bcd->isLinkable()) + { + ol.newParagraph(); + + QCString reimplFromLine = theTranslator->trReimplementedFromList(1); + int markerPos = reimplFromLine.find("@0"); + if (markerPos!=-1) // should always pass this. + { + parseText(ol,reimplFromLine.left(markerPos)); //text left from marker + if (bmd->isLinkable()) // replace marker with link + { + ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + bmd->anchor(),bcd->name()); + if ( bcd->isLinkableInProject()) + { + ol.writePageRef(bcd->name(),bmd->anchor()); + } + } + else + { + ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + 0,bcd->name()); + if (bcd->isLinkableInProject()) + { + ol.writePageRef(bcd->name(),0); + } + } + parseText(ol,reimplFromLine.right( + reimplFromLine.length()-markerPos-2)); // text right from marker + + } + else + { + err("Error: translation error: no marker in trReimplementsFromList()\n"); + } + } + + //ol.writeString("."); } - a=scopeTAL->next(); - if (a) result+=", "; + MemberList *bml=reimplementedBy(); + if (bml) + { + MemberListIterator mli(*bml); + MemberDef *bmd=0; + uint count=0; + ClassDef *bcd=0; + for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->memberClass());++mli) + { + // count the members that directly inherit from md and for + // which the member and class are visible in the docs. + if ( bmd->isLinkable() && bcd->isLinkable() ) count++; + } + if (count>0) + { + mli.toFirst(); + // write the list of classes that overwrite this member + ol.newParagraph(); + //parseText(ol,theTranslator->trReimplementedIn()); + //ol.writeString("Reimplemented in "); + //ol.docify(" "); + + QCString reimplInLine = + theTranslator->trReimplementedInList(count); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in reimplInLine with links to the classes + while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1) + { + parseText(ol,reimplInLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + //bmd=bml->at(entryIndex); + + count=0; + // find the entryIndex-th documented entry in the inheritance list. + for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->memberClass());++mli) + { + if ( bmd->isLinkable() && bcd->isLinkable()) + { + if (count==entryIndex) break; + count++; + } + } + + if (ok && bcd && bmd) // write link for marker + { + //if (bmd->hasDocumentation() && + // (bmd->protection()!=Private || Config::extractPrivateFlag) + // ) + //{ + ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + bmd->anchor(),bcd->name()); + if (bcd->isLinkableInProject()) + { + ol.writePageRef(bcd->name(),bmd->anchor()); + } + //} + //else + //{ + // ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), + // 0,bcd->name()); + // if (!bcd->isReference() && bcd->isVisible()) + // ol.writePageRef(bcd->name(),0); + //} + } + ++mli; + index=newIndex+matchLen; + } + parseText(ol,reimplInLine.right(reimplInLine.length()-index)); + + } + } + // write the list of examples that use this member + if (hasExamples()) + { + ol.startDescList(); + ol.startBold(); + parseText(ol,theTranslator->trExamples()+": "); + //ol.writeBoldString("Examples: "); + ol.endBold(); + ol.endDescTitle(); + ol.writeDescItem(); + writeExample(ol,getExampleList()); + //ol.endDescItem(); + ol.endDescList(); + } + ol.endIndent(); + // enable LaTeX again + //if (Config::extractAllFlag && !hasDocs) ol.enable(OutputGenerator::Latex); + } - result+=">"; - return result; +} + +void MemberDef::warnIfUndocumented() +{ + if (memberGroup) return; + ClassDef *cd = memberClass(); + NamespaceDef *nd = getNamespace(); + FileDef *fd = getFileDef(); + Definition *d=0; + const char *t=0; + if (cd) + t="class", d=cd; + else if (nd) + t="namespace", d=nd; + else + t="file", d=fd; + + if (d && d->isLinkable() && !isLinkable() && name().find('@')==-1) + warn("Warning: Member %s of %s %s is not documented\n", + name().data(),t,d->name().data()); +} + + +bool MemberDef::isLinkableInProject() +{ + return !name().isEmpty() && name().at(0)!='@' && + ((hasDocumentation() && !isReference()) || + (memberGroup && memberGroup->isLinkableInProject()) + ) && + (prot!=Private || Config::extractPrivateFlag || isFriend()); +} + +bool MemberDef::isLinkable() +{ + return isLinkableInProject() || isReference(); } diff --git a/src/memberdef.h b/src/memberdef.h index 4c1893f..68d9ad8 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -26,12 +26,13 @@ #include "config.h" #include "outputlist.h" #include "definition.h" -#include "config.h" +#include "scanner.h" class FileDef; class MemberList; class NamespaceDef; + class MemberDef : public Definition { public: @@ -55,14 +56,22 @@ class MemberDef : public Definition const ArgumentList *al); ~MemberDef(); + void writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd, + FileDef *fd,MemberGroup *mg); + void writeDeclaration(OutputList &ol,ClassDef *cd,NamespaceDef *nd,FileDef *fd, + int prevGroupId,bool inGroup); + void writeDocumentation(MemberList *ml,OutputList &ol, + const char *scopeName,MemberType m); + void warnIfUndocumented(); + QCString getOutputFileBase() const; const char *declaration() const { return decl; } const char *definition() const { return def; } const char *typeString() const { return type; } const char *argsString() const { return args; } const char *excpString() const { return exception; } - const char *anchor() const { return ref; } - QCString bodyCode() const { return body; } + const char *anchor() const { return anc; } + QCString bodyCode() const { return body; } ClassDef *memberClass() { return classDef; } Protection protection() const { return prot; } Specifier virtualness() const { return virt; } @@ -73,7 +82,7 @@ class MemberDef : public Definition void setDefLine(int l) { defLine=l; } void setFileDef(FileDef *fd) { fileDef=fd; } void setFileDec(FileDef *fd) { fileDec=fd; } - void setAnchor(const char *a) { ref=a; } + void setAnchor(const char *a) { anc=a; } void setProtection(Protection p) { prot=p; } void setBody(const QCString &b) { body=b; } FileDef *getFileDef() { return fileDef; } @@ -82,12 +91,11 @@ class MemberDef : public Definition bool isRelated() const { return related; } bool isStatic() const { return stat; } bool hasDocumentation() // overrides hasDocumentation in definition.h - { return !documentation().isNull() || - !briefDescription().isNull() || - !body.isEmpty() || - Config::extractAllFlag; - } + { return Definition::hasDocumentation() || !body.isEmpty(); } + bool isLinkableInProject(); + bool isLinkable(); + bool detailsAreVisible() const { return !documentation().isEmpty() || !body.isEmpty() || (mtype==Enumeration && docEnumValues) || @@ -142,9 +150,9 @@ class MemberDef : public Definition bool isPrototype() const { return proto; } // tag file related members - void setReference(const char *r) { external=r; } - bool isReference() { return !external.isNull(); } - + //void setReference(const char *r) { external=r; } + //bool isReference() { return !external.isNull(); } + // argument related members ArgumentList *argumentList() const { return argList; } void setArgumentList(ArgumentList *al) @@ -152,13 +160,28 @@ class MemberDef : public Definition argList = al; } ArgumentList *templateArguments() const { return tArgList; } - void setScopeTemplateArguments(ArgumentList *t); - ArgumentList *scopeTemplateArguments() const { return scopeTAL; } - QCString getScopeTemplateNameString(); + void setScopeDefTemplateArguments(ArgumentList *t); + ArgumentList *scopeDefTemplateArguments() const { return scopeTAL; } + void setMemberDefTemplateArguments(ArgumentList *t); + ArgumentList *memberDefTemplateArguments() const { return membTAL; } + //QCString getScopeTemplateNameString(); // namespace related members NamespaceDef *getNamespace() { return nspace; } void setNamespace(NamespaceDef *nd) { nspace=nd; } + + // grouping related members + void setGroupId(int groupId); + int groupId() const { return grpId; } + QCString groupHeader() const { return grpHeader; } + MemberGroup *getMemberGroup() const { return memberGroup; } + + void setFromAnnonymousScope(bool b) { annScope=b; } + void setFromAnnonymousMember(MemberDef *m) { annMemb=m; } + bool fromAnnonymousScope() { return annScope; } + bool annonymousDeclShown() { return annUsed; } + void setIndentDepth( int i) { indDepth=i; } + int indentDepth() { return indDepth; } private: ClassDef *classDef; // member of or related to @@ -174,34 +197,40 @@ class MemberDef : public Definition MemberList *enumFields; // enumeration fields OutputList *enumDeclList; // stored piece of documentation for enumeration. NamespaceDef *nspace; // the namespace this member is in. - QCString type; // return type - QCString args; // function arguments/variable array specifiers - QCString exception; // exceptions that can be thrown - QCString body; // function body code - QCString decl; // member declaration in class - QCString declFile; // file where the declaration was found + QCString type; // return type + QCString args; // function arguments/variable array specifiers + QCString exception; // exceptions that can be thrown + QCString body; // function body code + QCString decl; // member declaration in class + QCString declFile; // file where the declaration was found int declLine; // line where the declaration was found - QCString def; // member definition in code (fully qualified name) - QCString defFile; // file where the definition was found + QCString def; // member definition in code (fully qualified name) + QCString defFile; // file where the definition was found int defLine; // line where the definition was found - QCString ref; // HTML anchor name + QCString anc; // HTML anchor name Specifier virt; // normal/virtual/pure virtual Protection prot; // protection type [Public/Protected/Private] bool related; // is this a member that is only related to a class - QCString external; // anchor of a member if extracted from a tag file bool stat; // is it a static function? MemberType mtype; // returns the kind of member bool eUsed; // is the enumerate already placed in a list bool proto; // is it a prototype; bool docEnumValues; // is an enum with documented enum values. + bool annScope; + bool annUsed; + int indDepth; + MemberDef *annMemb; ArgumentList *argList; // argument list of this member ArgumentList *tArgList; // template argument list of function template ArgumentList *scopeTAL; // template argument list of class template + ArgumentList *membTAL; // template argument list of class template + int grpId; // group id + QCString grpHeader; // group header + MemberGroup *memberGroup; // group's member definition // disable copying of member defs MemberDef(const MemberDef &); MemberDef &operator=(const MemberDef &); }; - #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp new file mode 100644 index 0000000..883bfe2 --- /dev/null +++ b/src/membergroup.cpp @@ -0,0 +1,251 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 1997-1999 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * All output generated with Doxygen is not covered by this license. + * + */ + +#include "qtbc.h" +#include "membergroup.h" +#include "memberlist.h" +#include "outputlist.h" +#include "util.h" +#include "classdef.h" +#include "namespacedef.h" +#include "filedef.h" +#include "language.h" + +static QCString idToName(int id) +{ + QCString result; + result.sprintf("mgroup_%d",id); + return result; +} + +MemberGroup::MemberGroup(int id,const char *hdr) : Definition(idToName(id)) +{ + memberList = new MemberList; + grpId = id; + grpHeader = hdr; + fileName = name(); +} + +MemberGroup::~MemberGroup() +{ + delete memberList; +} + +void MemberGroup::insertMember(MemberDef *m) +{ + memberList->append(m); +} + +void MemberGroup::writeDocumentation(OutputList &ol) +{ + //printf("Writing documentation for group %s\n",fileName.data()); + + if (memberList->count()==0) return; // no member in this group! + + QCString title = grpHeader.copy(); + if (title.isEmpty()) + { + title = "Member Group"; // TODO: make translatable. + } + ol.disable(OutputGenerator::Man); + startFile(ol,fileName,title); + startTitle(ol); + ol.docify(title); + endTitle(ol,name()); + + + OutputList briefOutput(&ol); + if (!briefDescription().isEmpty()) + { + parseDoc(briefOutput,0,0,briefDescription()); + ol+=briefOutput; + ol.writeString(" \n"); + if (!documentation().isEmpty() || Config::repeatBriefFlag) + { + bool htmlEnabled = ol.isEnabled(OutputGenerator::Html); + bool latexEnabled = ol.isEnabled(OutputGenerator::Html); + if (htmlEnabled) ol.disableAllBut(OutputGenerator::Html); + if (latexEnabled) ol.disableAllBut(OutputGenerator::Html); + ol.startTextLink(0,"_details"); + parseText(ol,theTranslator->trMore()); + ol.endTextLink(); + if (htmlEnabled) ol.enable(OutputGenerator::Html); + if (latexEnabled) ol.enable(OutputGenerator::Latex); + } + } + // TODO: man page synopsis + + //if (memberList->count()>0) + //{ + QCString scopeName; + + MemberDef *md = memberList->first(); + ClassDef *cd = md->memberClass(); + NamespaceDef *nd = md->getNamespace(); + FileDef *fd = md->getFileDef(); + //printf("member %s brief=`%s' docs=`%s'\n", + // md->name().data(), md->briefDescription().data(), + // md->documentation().data()); + if (cd) + { + ol.newParagraph(); + ol.docify("Inside class "); + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(),0, + cd->name() + ); + scopeName=cd->name().copy(); + } + else if (nd) + { + ol.newParagraph(); + ol.docify("Inside namespace "); + ol.writeObjectLink(nd->getReference(), + nd->getOutputFileBase(),0, + nd->name() + ); + scopeName=nd->name().copy(); + } + else if (fd) + { + ol.newParagraph(); + ol.docify("#include <"); + ol.writeObjectLink(fd->getReference(), + fd->getOutputFileBase(),0, + fd->name() + ); + ol.docify(">"); + } + ol.startMemberSections(); + memberList->writeDeclarations(ol,cd,nd,fd,"Synopsis",0,TRUE); + ol.endMemberSections(); + + if ((!briefDescription().isEmpty() && Config::repeatBriefFlag) || + !documentation().isEmpty()) + { + ol.writeRuler(); + bool latexOn = ol.isEnabled(OutputGenerator::Latex); + if (latexOn) ol.disable(OutputGenerator::Latex); + ol.writeAnchor("_details"); + if (latexOn) ol.enable(OutputGenerator::Latex); + ol.startGroupHeader(); + parseText(ol,theTranslator->trDetailedDescription()); + ol.endGroupHeader(); + + // repeat brief description + if (!briefDescription().isEmpty() && Config::repeatBriefFlag) + { + ol+=briefOutput; + ol.newParagraph(); + } + // write documentation + if (!documentation().isEmpty()) + { + parseDoc(ol,scopeName,0,documentation()+"\n"); + } + } + +// memberList->countDocMembers(TRUE); +// +// if ( memberList->defineCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trDefineDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Define); +// } +// +// if ( memberList->protoCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trFunctionPrototypeDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Prototype); +// } +// +// if ( memberList->typedefCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trTypedefDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Typedef); +// } +// +// if ( memberList->enumCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trEnumerationTypeDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Enumeration); +// } +// +// if ( memberList->enumValueCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trEnumerationValueDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::EnumValue); +// } +// +// if ( memberList->funcCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trFunctionDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Function); +// } +// +// if ( memberList->varCount()>0 ) +// { +// ol.writeRuler(); +// ol.startGroupHeader(); +// parseText(ol,theTranslator->trVariableDocumentation()); +// ol.endGroupHeader(); +// writeMemberDocs(ol,memberList,scopeName,MemberDef::Variable); +// } + + endFile(ol); + ol.enable(OutputGenerator::Man); +} + +bool MemberGroup::isLinkableInProject() +{ + return hasDocumentation() && !isReference(); +} +bool MemberGroup::isLinkable() +{ + return isLinkableInProject() || isReference(); +} + +void MemberGroup::addDocumentation() +{ + //printf("adding documentation for membergroup %s\n",name().data()); + MemberListIterator mli(*memberList); + MemberDef *md; + for (;(md=mli.current());++mli) + { + //printf("Adding docs `%s' `%s'\n",md->briefDescription().data(),md->documentation().data()); + setBriefDescription(briefDescription()+"\n"+md->briefDescription()); + setDocumentation(documentation()+"\n"+md->documentation()); + } + //printf("isLinkable()=%d\n",isLinkable()); +} diff --git a/src/membergroup.h b/src/membergroup.h new file mode 100644 index 0000000..1db04df --- /dev/null +++ b/src/membergroup.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 1997-1999 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * All output generated with Doxygen is not covered by this license. + * + */ + +#ifndef MEMBERGROUP_H +#define MEMBERGROUP_H + +#include "qtbc.h" +#include <qlist.h> + +#include "definition.h" + +class MemberDef; +class MemberList; +class OutputList; + +class MemberGroup : public Definition +{ + public: + MemberGroup(int id,const char *header); + ~MemberGroup(); + QCString header() const { return grpHeader; } + QCString getOutputFileBase() const { return fileName; } + void insertMember(MemberDef *); + void writeDocumentation(OutputList &ol); + MemberList *members() const { return memberList; } + void addDocumentation(); + + bool isLinkableInProject(); + bool isLinkable(); + + private: + MemberList *memberList; // list of all members in the group + int grpId; + QCString grpHeader; + QCString fileName; // base name of the generated file +}; + +class MemberGroupList : public QList<MemberGroup> +{ +}; + +class MemberGroupListIterator : public QListIterator<MemberGroup> +{ + public: + MemberGroupListIterator(const MemberGroupList &l) : + QListIterator<MemberGroup>(l) {} +}; + +#endif diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 99ad00a..4f6bad9 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -18,6 +18,9 @@ #include "classdef.h" #include "message.h" #include <qregexp.h> +#include "util.h" +#include "language.h" +#include "doxygen.h" MemberList::MemberList() : QList<MemberDef>() { @@ -71,13 +74,14 @@ void MemberList::countDecMembers() } } -void MemberList::countDocMembers() +void MemberList::countDocMembers(bool inGroup) { varCnt=funcCnt=enumCnt=enumValCnt=typeCnt=protoCnt=defCnt=friendCnt=0; MemberDef *md=first(); while (md) { - if (Config::extractAllFlag || md->detailsAreVisible()) + if ((Config::extractAllFlag || md->detailsAreVisible()) && + (md->groupId()==-1 || inGroup)) { QRegExp r("@[0-9]+"); int dummy; @@ -142,3 +146,361 @@ MemberListIterator::MemberListIterator(const QList<MemberDef> &l) : { } +void MemberList::writePlainDeclarations(OutputList &ol,ClassDef *cd, + NamespaceDef *nd,FileDef *fd,bool inGroup) +{ + countDecMembers(); + if (totalCount()==0) return; // no members in this list + + int prevGroupId = -1; + if (!fd && !nd) ol.startMemberList(); + MemberDef *md; + + if (fd && defineCount()>0) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trDefines()); + ol.endMemberHeader(); + ol.startMemberList(); + MemberListIterator mli(*this); + for ( ; (md=mli.current()); ++mli ) + { + if (md->isDefine() && + (md->argsString() || md->hasDocumentation() || Config::extractAllFlag) + ) + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + } + ol.endMemberList(); + } + + if ((fd || nd) && protoCount()>0) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trFuncProtos()); + ol.endMemberHeader(); + ol.startMemberList(); + MemberListIterator mli(*this); + for ( ; (md=mli.current()); ++mli ) + { + if (md->isPrototype()) + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + } + ol.endMemberList(); + } + + if (typedefCount()>0) + { + if (fd || nd) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trTypedefs()); + ol.endMemberHeader(); + //ol.writeMemberHeader("Typedefs"); + ol.startMemberList(); + } + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + if (md->isTypedef()) + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + } + if (fd || nd) ol.endMemberList(); + } + + // write enums + if (enumCount()>0) + { + if (fd || nd) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trEnumerations()); + ol.endMemberHeader(); + ol.startMemberList(); + } + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + /*bool hasDocs=md->hasDocumentation();*/ + QCString type=md->typeString(); + type=type.stripWhiteSpace(); + if (md->isEnumerate() /*&& (hasDocs || !Config::hideMemberFlag)*/) + { + if (!Config::hideMemberFlag || // do not hide undocumented members or + !md->documentation().isEmpty() || // member has detailed descr. or + md->hasDocumentedEnumValues() || // member has documented enum vales. + Config::briefMemDescFlag || // brief descr. is shown or + Config::repeatBriefFlag // brief descr. is repeated. + ) + { + OutputList typeDecl(&ol); + QCString name=md->name().copy(); + int i=name.findRev("::"); + if (i!=-1) name=name.right(name.length()-i-2); // strip scope + if (name[0]!='@') // not an anonymous enum + { + //if (Config::extractAllFlag || + // (md->briefDescription().isEmpty() || !Config::briefMemDescFlag) && + // (!md->documentation().isEmpty() || md->hasDocumentedEnumValues() || + // (!md->briefDescription().isEmpty() && + // !Config::briefMemDescFlag && + // Config::repeatBriefFlag + // ) + // ) + // ) + if (md->hasDocumentation() || md->hasDocumentedEnumValues()) + { + if (Config::genTagFile.length()>0) + tagFile << md->name() << " " << md->anchor() + << " \"" << md->argsString() << "\""; + md->writeLink(typeDecl,cd,nd,fd,0); + } + else + { + typeDecl.writeBoldString(name); + } + typeDecl.writeChar(' '); + } + + typeDecl.docify("{ "); + QList<MemberDef> *fmdl=md->enumFieldList(); + if (fmdl) + { + MemberDef *fmd=fmdl->first(); + while (fmd) + { + if (fmd->hasDocumentation()) + { + if (Config::genTagFile.length()>0) + tagFile << fmd->name() << " " << fmd->anchor() + << " \"" << fmd->argsString() << "\""; + fmd->writeLink(typeDecl,cd,nd,fd,0); + } + else + typeDecl.writeBoldString(fmd->name()); + fmd=fmdl->next(); + if (fmd) typeDecl.writeString(", "); + typeDecl.disable(OutputGenerator::Man); + typeDecl.writeString("\n"); // to prevent too long lines in LaTeX + typeDecl.enable(OutputGenerator::Man); + } + } + typeDecl.docify(" }"); + md->setEnumDecl(typeDecl); + int enumVars=0; + MemberListIterator vmli(*this); + MemberDef *vmd; + if (name[0]=='@') // anonymous enum => append variables + { + for ( ; (vmd=vmli.current()) ; ++vmli) + { + QCString vtype=vmd->typeString(); + if ((vtype.find(name))!=-1) enumVars++; + } + } + if (enumVars==0) // no variable of this enum type + { + int gId = md->groupId(); + const char *gHeader = (gId!=prevGroupId && gId!=-1) ? + memberGroupDict[gId]->header().data() : 0; + ol.startMemberItem(gId!=-1,0); + ol.writeString("enum "); + ol.insertMemberAlign(); + ol+=typeDecl; + ol.endMemberItem(gId!=-1,md->anchor(),gHeader,FALSE); + //QCString brief=md->briefDescription(); + //brief=brief.stripWhiteSpace(); + if (!md->briefDescription().isEmpty() && Config::briefMemDescFlag + && gId==-1 && !inGroup) + { + ol.startMemberDescription(); + parseDoc(ol,cd?cd->name().data():0, + md->name().data(),md->briefDescription()); + if (!md->documentation().isEmpty() || md->hasDocumentedEnumValues()) + { + ol.disableAllBut(OutputGenerator::Html); + ol.endEmphasis(); + ol.docify(" "); + ol.startTextLink(0,md->anchor()); + parseText(ol,theTranslator->trMore()); + ol.endTextLink(); + ol.startEmphasis(); + ol.enableAll(); + } + ol.endMemberDescription(); + ol.disable(OutputGenerator::Man); + ol.newParagraph(); + ol.enable(OutputGenerator::Man); + } + } + md->warnIfUndocumented(); + prevGroupId = md->groupId(); + } + } // md->isEnumerate() + } // enum loop + if (fd || nd) ol.endMemberList(); + } // write enums + + // write functions + if (funcCount()>0) + { + if (fd || nd) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trFunctions()); + ol.endMemberHeader(); + ol.startMemberList(); + } + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + if ( md->isFunction() || md->isSignal() || + md->isSlot()) + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + } + if (fd || nd) ol.endMemberList(); + } + + if (friendCount()>0) + { + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + if ( md->isFriend()) + { + QCString type=md->typeString(); + //printf("Friend: type=%s name=%s\n",type.data(),md->name().data()); + if (md->hasDocumentation() && type!="friend class") + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + else // friend is undocumented as a member but it is a class, + // so generate a link to the class if that is documented. + { + int gId = md->groupId(); + const char *gHeader = (gId!=prevGroupId && gId!=-1) ? + memberGroupDict[gId]->header().data() : 0; + ClassDef *cd=getClass(md->name()); + if (md->hasDocumentation()) // friend is documented + { + ol.startMemberItem(gId!=-1,0); + ol.docify("class "); + ol.insertMemberAlign(); + ol.writeObjectLink(0,0,md->anchor(),md->name()); + ol.endMemberItem(gId!=-1,md->anchor(),gHeader,FALSE); + prevGroupId = md->groupId(); + } + else if (cd && cd->isLinkable()) // class is documented + { + ol.startMemberItem(gId!=-1,0); + ol.docify("class "); + ol.insertMemberAlign(); + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->name()); + ol.endMemberItem(gId!=-1,md->anchor(),gHeader,FALSE); + prevGroupId = md->groupId(); + } + else if (!Config::hideMemberFlag) // no documentation + { + ol.startMemberItem(gId!=-1,0); + ol.docify("class "); + ol.insertMemberAlign(); + ol.writeBoldString(md->name()); + ol.endMemberItem(gId!=-1,md->anchor(),gHeader,FALSE); + prevGroupId = md->groupId(); + } + } + } + } + } + + // write variables + if (varCount()>0) + { + if (fd || nd) + { + ol.startMemberHeader(); + parseText(ol,theTranslator->trVariables()); + ol.endMemberHeader(); + ol.startMemberList(); + } + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + if (md->isVariable()) + { + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + prevGroupId = md->groupId(); + } + } + if (fd || nd) ol.endMemberList(); + } + + // handle members that are inside annonymous compounds and for which + // no variables of the annonymous compound type exist. + if (cd) + { + MemberListIterator mli(*this); + for ( ; (md=mli.current()) ; ++mli ) + { + if (md->fromAnnonymousScope() && !md->annonymousDeclShown()) + { + md->setFromAnnonymousScope(FALSE); + md->writeDeclaration(ol,cd,nd,fd,prevGroupId,inGroup); + md->setFromAnnonymousScope(TRUE); + prevGroupId = md->groupId(); + } + } + } + + if (!fd && !nd) { ol.endMemberList(); /*ol.writeChar('\n');*/ } + + if (prevGroupId!=-1 && !inGroup) + { + ol.memberGroupSpacing(TRUE); + ol.memberGroupSeparator(); + } +} + +void MemberList::writeDeclarations(OutputList &ol,ClassDef *cd,NamespaceDef *nd, + FileDef *fd,const char *title,const char *subtitle,bool inGroup) +{ + countDecMembers(); + if (totalCount()==0) return; + if (title) + { + ol.startMemberHeader(); + parseText(ol,title); + ol.endMemberHeader(); + } + if (subtitle) + { + ol.startMemberSubtitle(); + parseText(ol,subtitle); + ol.endMemberSubtitle(); + } + + writePlainDeclarations(ol,cd,nd,fd,inGroup); +} + +void MemberList::writeDocumentation(OutputList &ol, + const char *scopeName, MemberDef::MemberType m) +{ + MemberListIterator mli(*this); + MemberDef *md; + for ( ; (md=mli.current()) ; ++mli) + { + md->writeDocumentation(this,ol,scopeName,m); + } +} diff --git a/src/memberlist.h b/src/memberlist.h index c26f055..abc84f2 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -38,10 +38,16 @@ class MemberList : public QList<MemberDef> int defineCount() const { return defCnt; } int friendCount() const { return friendCnt; } void countDecMembers(); - void countDocMembers(); + void countDocMembers(bool inGroup=FALSE); int totalCount() const { return varCnt+funcCnt+enumCnt+enumValCnt+typeCnt+ protoCnt+defCnt+friendCnt; } + void writePlainDeclarations(OutputList &ol,ClassDef *cd, + NamespaceDef *nd,FileDef *fd,bool inGroup=FALSE); + void writeDeclarations(OutputList &ol,ClassDef *cd,NamespaceDef *nd,FileDef *fd, + const char *title,const char *subtitle,bool inGroup=FALSE); + void writeDocumentation(OutputList &ol,const char *scopeName, + MemberDef::MemberType m); private: int varCnt,funcCnt,enumCnt,enumValCnt,typeCnt,protoCnt,defCnt,friendCnt; diff --git a/src/membername.cpp b/src/membername.cpp index 2605f86..eb28091 100644 --- a/src/membername.cpp +++ b/src/membername.cpp @@ -50,10 +50,6 @@ MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>() setAutoDelete(TRUE); } -MemberNameInfo::~MemberNameInfo() -{ -} - int MemberNameInfo::compareItems(GCI item1, GCI item2) { MemberInfo *m1=(MemberInfo *)item1; diff --git a/src/membername.h b/src/membername.h index c485dc8..a9454f9 100644 --- a/src/membername.h +++ b/src/membername.h @@ -70,7 +70,6 @@ class MemberNameInfo : public QList<MemberInfo> { public: MemberNameInfo(const char *name); - ~MemberNameInfo(); const char *memberName() const { return name; } int compareItems(GCI item1,GCI item2); private: diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 2574563..d8388a0 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -30,7 +30,7 @@ NamespaceDef::NamespaceDef(const char *name,const char *ref) : Definition(name) fileName="namespace_"+nameToFile(name); classList = new ClassList; memList = new MemberList; - reference=ref; + setReference(ref); } NamespaceDef::~NamespaceDef() @@ -94,7 +94,7 @@ void NamespaceDef::writeDocumentation(OutputList &ol) bool found=FALSE; while (cd) { - if (cd->isVisibleExt()) + if (cd->isLinkable()) { if (!found) { @@ -110,12 +110,13 @@ void NamespaceDef::writeDocumentation(OutputList &ol) clName = clName.right(clName.length()-name().length()-2); } - ol.startMemberItem(); + ol.startMemberItem(FALSE,0); switch (cd->compoundType()) { - case ClassDef::Class: ol.writeString("class"); break; - case ClassDef::Struct: ol.writeString("struct"); break; - case ClassDef::Union: ol.writeString("union"); break; + case ClassDef::Class: ol.writeString("class"); break; + case ClassDef::Struct: ol.writeString("struct"); break; + case ClassDef::Union: ol.writeString("union"); break; + case ClassDef::Interface: ol.writeString("interface"); break; } ol.writeString(" "); ol.insertMemberAlign(); @@ -133,14 +134,14 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.docify(clName); ol.endBold(); } - ol.endMemberItem(); + ol.endMemberItem(FALSE,0,0,FALSE); } cd=classList->next(); } if (found) ol.endMemberList(); } - writeMemberDecs(ol,0,this,0,0,0,memList); + memList->writeDeclarations(ol,0,this,0,0,0); ol.endMemberSections(); if (!briefDescription().isEmpty() || !documentation().isEmpty()) @@ -173,7 +174,7 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trFunctionPrototypeDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Prototype); + memList->writeDocumentation(ol,name(),MemberDef::Prototype); } if ( memList->typedefCount()>0 ) @@ -182,7 +183,7 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trTypedefDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Typedef); + memList->writeDocumentation(ol,name(),MemberDef::Typedef); } if ( memList->enumCount()>0 ) @@ -191,7 +192,7 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trEnumerationTypeDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Enumeration); + memList->writeDocumentation(ol,name(),MemberDef::Enumeration); } if ( memList->enumValueCount()>0 ) @@ -200,16 +201,19 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trEnumerationValueDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::EnumValue); + memList->writeDocumentation(ol,name(),MemberDef::EnumValue); } - if ( memList->funcCount()>0 ) + int cnt; + if ( (cnt=memList->funcCount()>0) ) { ol.writeRuler(); ol.startGroupHeader(); - parseText(ol,theTranslator->trFunctionDocumentation()); + QCString cntString; + //cntString.sprintf(" (%d)",cnt); + parseText(ol,theTranslator->trFunctionDocumentation()+cntString); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Function); + memList->writeDocumentation(ol,name(),MemberDef::Function); } if ( memList->varCount()>0 ) @@ -218,7 +222,7 @@ void NamespaceDef::writeDocumentation(OutputList &ol) ol.startGroupHeader(); parseText(ol,theTranslator->trVariableDocumentation()); ol.endGroupHeader(); - writeMemberDocs(ol,memList,name(),MemberDef::Variable); + memList->writeDocumentation(ol,name(),MemberDef::Variable); } // write Author section (Man only) diff --git a/src/namespacedef.h b/src/namespacedef.h index ca25700..e68fa3f 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -41,20 +41,32 @@ class NamespaceDef : public Definition void insertMember(MemberDef *md); void computeAnchors(); int countMembers(); - const char *getReference() { return reference; } - bool isVisible() + //const char *getReference() { return reference; } + //bool isVisible() + //{ + // return !getReference() && hasDocumentation() && + // !name().isEmpty() && name().at(0)!='@'; + //} + //bool isVisibleExt() + //{ + // return (getReference() || hasDocumentation()) && + // !name().isEmpty() && name().at(0)!='@'; + //} + + bool isLinkableInProject() { - return !getReference() && hasDocumentation() && - !name().isEmpty() && name().at(0)!='@'; + int i = name().findRev("::"); + if (i==-1) i=0; else i+=2; + return !name().isEmpty() && name().at(i)!='@' && + hasDocumentation() && !isReference(); } - bool isVisibleExt() + bool isLinkable() { - return (getReference() || hasDocumentation()) && - !name().isEmpty() && name().at(0)!='@'; + return isLinkableInProject() || isReference(); } private: - QCString reference; + //QCString reference; QCString fileName; QStrList files; ClassList *classList; @@ -79,6 +91,10 @@ class NamespaceListIterator : public QListIterator<NamespaceDef> QListIterator<NamespaceDef>(l) {} }; -typedef QDict<NamespaceDef> NamespaceDict; +class NamespaceDict : public QDict<NamespaceDef> +{ + public: + NamespaceDict(int size) : QDict<NamespaceDef>(size) {} +}; #endif diff --git a/src/outputgen.h b/src/outputgen.h index 7411d5c..778705c 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -67,6 +67,9 @@ class OutputGenerator virtual void endEnumList() = 0; virtual void startBold() = 0; virtual void endBold() = 0; + virtual void startAlfabeticalIndexList() = 0; + virtual void endAlfabeticalIndexList() = 0; + virtual void writeIndexHeading(const char *s) = 0; virtual void writeIndexItem(const char *ref,const char *file, const char *text) = 0; virtual void docify(const char *s) = 0; @@ -92,8 +95,10 @@ class OutputGenerator virtual void endMemberSubtitle() = 0; virtual void startMemberList() = 0; virtual void endMemberList() = 0; - virtual void startMemberItem() = 0; - virtual void endMemberItem() = 0; + virtual void startMemberItem(bool,int) = 0; + virtual void endMemberItem(bool,const char *,const char *,bool) = 0; + virtual void memberGroupSpacing(bool) = 0; + virtual void memberGroupSeparator() = 0; virtual void insertMemberAlign() = 0; virtual void writeRuler() = 0; @@ -165,6 +170,7 @@ class OutputGenerator virtual void startQuickIndexItem(const char *s,const char *l) = 0; virtual void endQuickIndexItem() = 0; virtual void writeFormula(const char *,const char *) = 0; + virtual void writeNonBreakableSpace() = 0; void clear() { b.close(); a.resize(0); b.setBuffer(a); b.open(IO_WriteOnly); t.setDevice(&b); } diff --git a/src/outputlist.cpp b/src/outputlist.cpp index daa83ed..ae86c89 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -226,14 +226,18 @@ void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4),a1,a2,a3,a4) FORALL1(const char *a1,a1) FORALL1(char a1,a1) FORALL1(int a1,a1) +FORALL1(bool a1,a1) FORALL1(IndexSections a1,a1) FORALL2(const char *a1,const char *a2,a1,a2) FORALL2(int a1,bool a2,a1,a2) +FORALL2(bool a1,int a2,a1,a2) +FORALL2(bool a1,bool a2,a1,a2) FORALL3(ClassDiagram &a1,const char *a2,const char *a3,a1,a2,a3) FORALL3(const char *a1,const char *a2,const char *a3,a1,a2,a3) FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3) FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3) FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4) +FORALL4(bool a1,const char *a2,const char *a3,bool a4,a1,a2,a3,a4) //-------------------------------------------------------------------------- diff --git a/src/outputlist.h b/src/outputlist.h index 8f66f63..79ee93f 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -96,6 +96,12 @@ class OutputList { forall(&OutputGenerator::startEnumList); } void endEnumList() { forall(&OutputGenerator::endEnumList); } + void startAlfabeticalIndexList() + { forall(&OutputGenerator::startAlfabeticalIndexList); } + void endAlfabeticalIndexList() + { forall(&OutputGenerator::endAlfabeticalIndexList); } + void writeIndexHeading(const char *s) + { forall(&OutputGenerator::writeIndexHeading,s); } void writeIndexItem(const char *ref,const char *file,const char *text) { forall(&OutputGenerator::writeIndexItem,ref,file,text); } void docify(const char *s) @@ -145,10 +151,14 @@ class OutputList { forall(&OutputGenerator::startMemberList); } void endMemberList() { forall(&OutputGenerator::endMemberList); } - void startMemberItem() - { forall(&OutputGenerator::startMemberItem); } - void endMemberItem() - { forall(&OutputGenerator::endMemberItem); } + void startMemberItem(bool b1,int i1) + { forall(&OutputGenerator::startMemberItem,b1,i1); } + void endMemberItem(bool b1,const char *n1,const char *n2,bool b2) + { forall(&OutputGenerator::endMemberItem,b1,n1,n2,b2); } + void memberGroupSpacing(bool b) + { forall(&OutputGenerator::memberGroupSpacing,b); } + void memberGroupSeparator() + { forall(&OutputGenerator::memberGroupSeparator); } void insertMemberAlign() { forall(&OutputGenerator::insertMemberAlign); } void writeRuler() @@ -287,6 +297,8 @@ class OutputList { forall(&OutputGenerator::endQuickIndexItem); } void writeFormula(const char *n,const char *t) { forall(&OutputGenerator::writeFormula,n,t); } + void writeNonBreakableSpace() + { forall(&OutputGenerator::writeNonBreakableSpace); } private: void debug(); @@ -296,14 +308,18 @@ class OutputList FORALLPROTO1(const char *); FORALLPROTO1(char); FORALLPROTO1(int); + FORALLPROTO1(bool); FORALLPROTO1(IndexSections); FORALLPROTO2(const char *,const char *); FORALLPROTO2(int,bool); + FORALLPROTO2(bool,int); + FORALLPROTO2(bool,bool); FORALLPROTO3(const char *,const char *,bool); FORALLPROTO3(uchar,uchar,uchar); FORALLPROTO3(const char *,const char *,const char *); FORALLPROTO3(ClassDiagram &,const char *,const char *); FORALLPROTO4(const char *,const char *,const char *,const char *); + FORALLPROTO4(bool,const char *,const char *,bool); OutputList(const OutputList &ol); QList<OutputGenerator> *outputs; @@ -294,9 +294,6 @@ static bool replaceFunctionMacro(const QCString &expr,QCString *rest,int pos,int len=0; result.resize(0); int cc; - // TODO: use a checkNextChar function. - //while ((cc=getNextChar(expr,rest,j))!=EOF && cc==' ') len++; - //if (cc!='(') return FALSE; while ((cc=getCurrentChar(expr,rest,j))!=EOF && cc==' ') { len++; @@ -329,8 +326,8 @@ static bool replaceFunctionMacro(const QCString &expr,QCString *rest,int pos,int } else { - while ((argCount<def->nargs || def->varArgs) && - ((cc=getNextChar(expr,rest,j))!=EOF) && !done + while (!done && (argCount<def->nargs || def->varArgs) && + ((cc=getNextChar(expr,rest,j))!=EOF) ) { char c=(char)cc; @@ -586,13 +583,17 @@ static void expandExpression(QCString &expr,QCString *rest,int pos) if (replaced) // expand the macro and rescan the expression { + //printf("replacing `%s'->`%s'\n",expr.mid(p,len).data(),expMacro.data()); QCString resultExpr=expMacro; QCString restExpr=expr.right(expr.length()-len-p); processConcatOperators(resultExpr); - expandedDict->insert(macroName,def); - expandExpression(resultExpr,&restExpr,0); - expandedDict->remove(macroName); + if (!def->nonRecursive) + { + expandedDict->insert(macroName,def); + expandExpression(resultExpr,&restExpr,0); + expandedDict->remove(macroName); + } expr=expr.left(p)+resultExpr+restExpr; i=p; //printf("new expression: %s\n",expr.data()); @@ -708,7 +709,6 @@ bool computeExpression(const QCString &expr) expandExpression(e,0,0); e = removeIdsAndMarkers(e); if (e.length()==0) return FALSE; - //printf("computeExpession(%s)\n",e.data()); return parseCppExpression(e); } @@ -890,7 +890,8 @@ BN [ \t\r\n] if (includeStack.isEmpty() && Config::macroExpansionFlag && /* (expandDefine=fileDefineCache->findDefine(yyFileName,yytext)) */ - (def=fileDefineDict->find(yytext)) + (def=fileDefineDict->find(yytext)) && + (!Config::onlyPredefinedFlag || def->isPredefined) ) { //printf("Found it!\n"); @@ -899,6 +900,7 @@ BN [ \t\r\n] if (def->nargs==-1) // no function macro { QCString result = expandMacro(defArgsStr); + //printf("result=`%s'\n",result.data()); outputArray(result,result.length()); } else // zero or more arguments @@ -918,12 +920,14 @@ BN [ \t\r\n] if (includeStack.isEmpty() && Config::macroExpansionFlag && (def=fileDefineDict->find(yytext)) && - def->nargs==-1 + def->nargs==-1 && + (!Config::onlyPredefinedFlag || def->isPredefined) ) { //printf("Found it!\n"); QCString name=yytext; QCString result=expandMacro(name); + //printf("result=`%s'\n",result.data()); outputArray(result,result.length()); } else @@ -948,6 +952,7 @@ BN [ \t\r\n] roundCount--; if (roundCount==0) { + //printf("defArgsStr=`%s'\n",defArgsStr.data()); QCString result=expandMacro(defArgsStr); if (findDefArgContext==CopyLine) { @@ -987,6 +992,9 @@ BN [ \t\r\n] defArgsStr+=*yytext; BEGIN(FindDefineArgs); } +<ReadString>"//"|"/*" { + defArgsStr+=yytext; + } <ReadString>. { defArgsStr+=*yytext; } @@ -1273,7 +1281,7 @@ BN [ \t\r\n] //{ // addDefine(); //} - if (!Config::onlyPredefinedFlag && (def=fileDefineDict->find(defName))==0) + if (/*!Config::onlyPredefinedFlag &&*/ (def=fileDefineDict->find(defName))==0) { fileDefineDict->insert(defName,newDefine()); } @@ -1300,7 +1308,7 @@ BN [ \t\r\n] } <DefineArg>","{B}* { defArgsStr+=yytext; } <DefineArg>"("{B}* { defArgsStr+=yytext; } -<DefineArg>")"{B}* { +<DefineArg>{B}*")"{B}* { defArgsStr+=yytext; QCString tmp=(QCString)"#define "+defName+defArgsStr; outputArray(tmp.data(),tmp.length()); @@ -1421,7 +1429,7 @@ BN [ \t\r\n] { addDefine(); } - if (!Config::onlyPredefinedFlag && (def=fileDefineDict->find(defName))==0) + if (/*!Config::onlyPredefinedFlag &&*/ (def=fileDefineDict->find(defName))==0) { fileDefineDict->insert(defName,newDefine()); } @@ -1460,6 +1468,9 @@ BN [ \t\r\n] defText += *yytext; BEGIN(DefineText); } +<SkipSingleQuote,SkipDoubleQuote>\\. { + defText += yytext; + } <SkipSingleQuote>\' { defText += *yytext; BEGIN(DefineText); @@ -1629,6 +1640,7 @@ void preprocessFile(const char *fileName,BufStr &output) int i_equals=ds.find('='); int i_obrace=ds.find('('); int i_cbrace=ds.find(')'); + bool nonRecursive = i_equals>0 && ds.at(i_equals-1)==':'; if (i_obrace==0) continue; // no define name @@ -1676,6 +1688,8 @@ void preprocessFile(const char *fileName,BufStr &output) def->name = ds.left(i_obrace); def->definition = definition; def->nargs = count; + def->isPredefined = TRUE; + def->nonRecursive = nonRecursive; fileDefineDict->insert(def->name,def); //printf("#define `%s' `%s' #nargs=%d\n", @@ -1694,10 +1708,13 @@ void preprocessFile(const char *fileName,BufStr &output) } else // simple define with argument { - def->name = ds.left(i_equals); + int ine=i_equals - (nonRecursive ? 1 : 0); + def->name = ds.left(ine); def->definition = ds.right(ds.length()-i_equals-1); } def->nargs = -1; + def->isPredefined = TRUE; + def->nonRecursive = nonRecursive; fileDefineDict->insert(def->name,def); //printf("#define `%s' `%s' #nargs=%d\n", diff --git a/src/scanner.h b/src/scanner.h index 1e6bad7..30894cd 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -20,11 +20,15 @@ #include "qtbc.h" #include <stdio.h> #include <qlist.h> +#include <qintdict.h> #include "entry.h" #include "code.h" +#include "membergroup.h" class OutputList; +typedef QIntDict<MemberGroup> MemberGroupDict; +typedef QIntDictIterator<MemberGroup> MemberGroupDictIterator; extern void parseMain(Entry *); extern void parseDoc(OutputList &ol,const char *clName, const char *memName, @@ -32,4 +36,7 @@ extern void parseDoc(OutputList &ol,const char *clName, const char *memName, extern void parseExample(OutputList &ol,const QCString &docString, const char *fileName); extern void parseText(OutputList &ol,const QCString &txtString); + +extern MemberGroupDict memberGroupDict; + #endif diff --git a/src/scanner.l b/src/scanner.l index 9c7b477..c3c4ade 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -46,6 +46,9 @@ #define YY_NEVER_INTERACTIVE 1 + +MemberGroupDict memberGroupDict(1009); // dictionary of the member groups heading + /* ----------------------------------------------------------------- * * statics @@ -75,6 +78,7 @@ static int lastCurlyContext; static int lastCodeState; static int lastAfterDocContext; static int lastGroupContext; +static int lastMemberGroupContext; static int lastFormulaContext; static int lastAnchorContext; static int nextDefContext; @@ -93,6 +97,7 @@ static Entry* tempEntry = 0 ; static int yyLineNr = 0 ; static int anonCount = 0 ; static char yyFileName[2048] ; +static int lastMemberGroupLine; static bool sig; static bool slot; static bool gstat; @@ -104,6 +109,7 @@ static QCString exampleName; static QCString htmlUrl,htmlText; static QCString currentIncludeFile; static QCString msType,msName,msArgs; +static int memberGroupId = -1; static int includeFileOffset = 0; static int includeFileLength = 0; static bool firstLine; @@ -141,7 +147,8 @@ static int lastCopyArgStringContext; static int lastCopyArgContext; static QCString *copyArgString; - +static ArgumentList *currentArgumentList; +static QCString *currentTemplateSpec; //----------------------------------------------------------------------------- @@ -168,6 +175,7 @@ static void initParser() sharpCount = 0; roundCount = 0; ifCount = 0; + memberGroupId = -1; sig = FALSE; slot = FALSE; gstat = FALSE; @@ -513,8 +521,15 @@ static void showUntil(OutputList &ol,const char *key) } } +static int newMemberGroupId() +{ + static int curGroupId=0; + return curGroupId++; +} + static void newDocState(); + //----------------------------------------------------------------- static bool inBlock() @@ -578,6 +593,20 @@ static bool nameIsOperator(QCString &name) (name.length()==8 || !isId(name.at(name.length()-9))); } +static void checkDocs() +{ + if ((current->brief.length()>2 && + current->brief.at(0)=='<' && current->brief.at(1)==' ') || + (current->doc.length()>2 && + current->doc.at(0)=='<' && current->doc.at(1)==' ') + ) + { + warn("Warning: Found lonely '<' symbol at the start of the documentation " + "at line %d of %s\n",yyLineNr,yyFileName); + + } +} + /* ----------------------------------------------------------------- */ static void addToBody(const char *text); @@ -715,6 +744,7 @@ VAR [vV][aA][rR] %x GroupDocArg1 %x GroupDocArg2 %x GroupName +%x GroupHeader %x AfterDoc %x AfterDocBrief %x AfterDocLine @@ -775,6 +805,7 @@ VAR [vV][aA][rR] %x DocRefItemName %x SectionLabel %x SectionTitle +%x SkipTemplate %x EndTemplate %x CopyArgString %x CopyArgRound @@ -790,6 +821,11 @@ VAR [vV][aA][rR] %% <*>\x06[^\x06]*\x06 { // new file + if (memberGroupId!=-1) + { + warn("Warning: Missing \\endmgroup in file %s\n",yyFileName); + memberGroupId=-1; + } yyLineNr= 1 ; int i; for( i = 0 ; yytext[i+1] != 6 ; i++ ) @@ -1263,7 +1299,7 @@ VAR [vV][aA][rR] warn("Warning: \\endcode without <PRE> or \\code " "in the documentation of %s\n",refName.data()); } -<DocScan>{SCOPEMASK}"("[a-z_A-Z,\<\> \t\*\&]+")" { +<DocScan>{SCOPEMASK}"("[a-z_A-Z,:\<\> \t\*\&]+")" { generateRef(*outDoc,className,yytext,inSeeBlock); } <DocScan>{SCOPEMASK}(("()")?) { @@ -1690,9 +1726,28 @@ VAR [vV][aA][rR] lineCount(); BEGIN( ClassName ); } +<FindMembers>{B}*"module"{BN}+ { + isTypedef=FALSE; + current->section = Entry::NAMESPACE_SEC; + current->type = "module" ; + current->fileName = yyFileName; + current->startLine = yyLineNr; + lineCount(); + BEGIN( ClassName ); + } +<FindMembers>{B}*"interface"{BN}+ { + isTypedef=FALSE; + current->section = Entry::INTERFACE_SEC; + addType( current ) ; + current->type += " interface" ; + current->fileName = yyFileName; + current->startLine = yyLineNr; + lineCount(); + BEGIN( ClassName ); + } <FindMembers>{B}*(("typedef"{BN}+)?)"class"{BN}+ { isTypedef=((QCString)yytext).find("typedef")!=-1; - current->section = Entry::CLASS_SEC ; + current->section = Entry::CLASS_SEC; addType( current ) ; current->type += " class" ; current->fileName = yyFileName; @@ -1747,16 +1802,35 @@ VAR [vV][aA][rR] } <FindMembers>"template"({BN}*)"<"/[>]? { lineCount(); - if (current->tArgList) + // class template specifier already found => member template specifier + // already inside class => member template specifier + if (current->tArgList || (current_root->section&Entry::COMPOUND_MASK)) { - //printf("scanner.l current->tArgList->clear() %p\n",current->tArgList); - current->tArgList->clear(); + //printf("-------> member template\n"); + if (current->mtArgList) + { + current->mtArgList->clear(); + } + else + { + current->mtArgList = new ArgumentList; + current->mtArgList->setAutoDelete(TRUE); + } + currentArgumentList = current->mtArgList; } - else + else // class template specifier { - current->tArgList = new ArgumentList; - current->tArgList->setAutoDelete(TRUE); - //printf("scanner.l new tArgList %p\n",current->tArgList); + //printf("-------> class template\n"); + if (current->tArgList) + { + current->tArgList->clear(); + } + else + { + current->tArgList = new ArgumentList; + current->tArgList->setAutoDelete(TRUE); + } + currentArgumentList = current->tArgList; } templateStr="<"; copyArgString=&templateStr; @@ -1764,28 +1838,7 @@ VAR [vV][aA][rR] //printf("Start template list\n"); BEGIN( ReadTempArgs ); } - /* -<FindMembers>({ID}{BN}*"::")*{BN}*"operator"{BN}*[<=]+ { - lineCount(); - addType( current ); - current->name = yytext; - } -<FindMembers>"operator"{BN}*"/"[=]?/[^/ *] { space added! - lineCount(); - addType( current ); - current->name = yytext; - } -<FindMembers>"operator"{BN}*"({B}*)"{BN}* /"(" { space added! - lineCount(); - addType( current ); - current->name = yytext; - } -<FindMembers>"operator"{BN}*[^(/]+ { - lineCount(); - addType( current ) ; - current->name = yytext ; - } - */ + /* for now the using statement is completely ignored */ <FindMembers>"using"{BN}+ { lineCount(); BEGIN(Using); } <Using>";" { BEGIN(FindMembers); } <FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl @@ -1799,20 +1852,45 @@ VAR [vV][aA][rR] addType( current ); current->name=yytext; current->name=current->name.stripWhiteSpace(); + current->scopeSpec.resize(0); + currentTemplateSpec = ¤t->scopeSpec; if (nameIsOperator(current->name)) BEGIN( Operator ); else BEGIN( EndTemplate ); } +<FindMemberName>{SCOPENAME}{BN}*/"<" { + sharpCount=0; + lineCount(); + current->name+=((QCString)yytext).stripWhiteSpace(); + current->memberSpec.resize(0); + currentTemplateSpec = ¤t->memberSpec; + if (nameIsOperator(current->name)) + BEGIN( Operator ); + else + BEGIN( EndTemplate ); + } + /* +<SkipTemplate>"<" { + sharpCount++; + } +<SkipTemplate>">" { + if (--sharpCount<=0) + { + BEGIN(FindMembers); + } + } +<SkipTemplate>. + */ + <EndTemplate>"<" { - current->name+='<'; + current->name+='<'; + *currentTemplateSpec+='<'; sharpCount++; } - /* -<EndTemplate>">"({BN}*"::"{SCOPENAME})? { - */ <EndTemplate>">" { - current->name+=*yytext; + current->name+='>'; + *currentTemplateSpec+='>'; if (--sharpCount<=0) { //printf("Found %s\n",current->name.data()); @@ -1821,7 +1899,8 @@ VAR [vV][aA][rR] } <EndTemplate>">"{BN}*"(" { lineCount(); - current->name+='>'; + current->name+='>'; + *currentTemplateSpec+='>'; if (--sharpCount<=0) { current->args = "("; @@ -1834,12 +1913,16 @@ VAR [vV][aA][rR] <EndTemplate>">"{BN}*/"::" { lineCount(); current->name+='>'; + *currentTemplateSpec+='>'; if (--sharpCount<=0) { BEGIN(FindMemberName); } } -<EndTemplate>. { current->name+=*yytext; } +<EndTemplate>. { + current->name+=*yytext; + *currentTemplateSpec+=*yytext; + } <FindMembers,FindMemberName>{SCOPENAME} { lineCount(); if (YY_START==FindMembers) @@ -1857,10 +1940,10 @@ VAR [vV][aA][rR] else BEGIN(FindMembers); } -<FindMembers>^{B}*"#" { lastCPPContext = YY_START; +<FindMembers>{B}*"#" { lastCPPContext = YY_START; BEGIN( SkipCPP ) ; } -<FindMembers>^{B}*"#define" { +<FindMembers>{B}*"#"{B}*"define" { BEGIN( Define ); } <SkipCPP>. @@ -1908,45 +1991,66 @@ VAR [vV][aA][rR] <FindMembers>[*&]+ { current->name += yytext ; } <FindMembers,MemberSpec,Function,NextSemi>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); - current->doc.resize(0); - current->brief.resize(0); lastAfterDocContext = YY_START; afterDocTerminator = ';'; if (yytext[yyleng-3]=='/') + { + current->brief.resize(0); BEGIN(AfterDocLine); + } else if (yytext[yyleng-2]=='*' && Config::autoBriefFlag) + { + current->brief.resize(0); BEGIN(AfterDocBrief); + } else + { + current->doc.resize(0); BEGIN(AfterDoc); + } } <MemberSpec,FindFields,FindMembers,NextSemi>","{BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); - current->doc.resize(0); - current->brief.resize(0); lastAfterDocContext = YY_START; afterDocTerminator = ','; if (yytext[yyleng-3]=='/') + { + current->brief.resize(0); BEGIN(AfterDocLine); + } else if (yytext[yyleng-2]=='*' && Config::autoBriefFlag) + { + current->brief.resize(0); BEGIN(AfterDocBrief); + } else + { + current->doc.resize(0); BEGIN(AfterDoc); + } } <DefineEnd,FindFields,FindFieldArg>{BN}*("/**"|"//!"|"/*!"|"///")"<" { lineCount(); - current->doc.resize(0); - current->brief.resize(0); lastAfterDocContext = YY_START; if (YY_START==DefineEnd) afterDocTerminator = '\n'; else afterDocTerminator = 0; if (yytext[yyleng-3]=='/') + { + current->brief.resize(0); BEGIN(AfterDocLine); + } else if (yytext[yyleng-2]=='*' && Config::autoBriefFlag) + { + current->brief.resize(0); BEGIN(AfterDocBrief); + } else + { + current->doc.resize(0); BEGIN(AfterDoc); + } } <FindMembers>"=" { BEGIN(NextSemi); @@ -2326,7 +2430,7 @@ VAR [vV][aA][rR] <ReadTempArgs>">" { *copyArgString+=*yytext; //printf("end template list %s\n",copyArgString->data()); - stringToArgumentList(*copyArgString,current->tArgList); + stringToArgumentList(*copyArgString,currentArgumentList); BEGIN( currentArgumentContext ); } <CopyArgRound>"(" { @@ -2496,6 +2600,9 @@ VAR [vV][aA][rR] current->proto = TRUE; } } + //printf("Adding entry `%s' groupId=%d groupHeader=`%s'\n", + // current->name.data(),current->mGrpId,current->mGrpId!=-1 ? + // memberGroupDict[current->mGrpId]->header().data() : ""); previous = current; current_root->addSubEntry(current); current = new Entry ; @@ -2504,6 +2611,7 @@ VAR [vV][aA][rR] current->virt = virt; current->stat = gstat; current->slot = slot; + current->mGrpId = memberGroupId; lastCurlyContext = FindMembers; if( *yytext == '{' ) { @@ -2658,14 +2766,17 @@ VAR [vV][aA][rR] current->name = yytext ; //BEGIN( FindMembers ); } -<ClassVar>"(" { - roundCount=1; - lastSkipRoundContext=YY_START; - BEGIN(SkipRound); +<ClassVar>[(\[] { + // probably a function anyway + unput('('); + BEGIN( FindMembers ); } <ClassVar>":" { current->type.resize(0); - baseProt=Private; + if (current->section == Entry::INTERFACE_SEC) + baseProt=Public; + else + baseProt=Private; baseVirt=Normal; baseName.resize(0); BEGIN( Bases ) ; @@ -2676,6 +2787,7 @@ VAR [vV][aA][rR] } <ClassName,ClassVar>{B}*"{"{B}* { current->fileName = yyFileName ; current->startLine = yyLineNr ; + current->name = removeRedundantWhiteSpace(current->name); if (current->name.length()==0 && !isTypedef) // anonymous compound current->name.sprintf("@%d",anonCount++); BEGIN( Curly ) ; @@ -2725,6 +2837,7 @@ VAR [vV][aA][rR] BEGIN ( lastSkipRoundContext ); } <Bases>"," { current->args += ',' ; + current->name = removeRedundantWhiteSpace(current->name); if (baseName.length()>0) current->extends->append( new BaseInfo(baseName,baseProt,baseVirt) @@ -2735,6 +2848,7 @@ VAR [vV][aA][rR] } <Bases>{B}*"{"{B}* { current->fileName = yyFileName ; current->startLine = yyLineNr ; + current->name = removeRedundantWhiteSpace(current->name); if (baseName.length()>0) current->extends->append( new BaseInfo(baseName,baseProt,baseVirt) @@ -2935,6 +3049,12 @@ VAR [vV][aA][rR] current->startLine = yyLineNr; BEGIN( ClassDocArg1 ); } +<Doc,JavaDoc>{B}*("\\"|"@")"interface"{B}* { + current->section = Entry::INTERFACEDOC_SEC; + current->fileName = yyFileName; + current->startLine = yyLineNr; + BEGIN( ClassDocArg1 ); + } <Doc,JavaDoc>{B}*("\\"|"@")"page"{B}* { current->section = Entry::PAGEDOC_SEC; current->fileName = yyFileName; @@ -3076,6 +3196,35 @@ VAR [vV][aA][rR] sectionType=SectionInfo::Subsection; BEGIN(SectionLabel); } +<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")mgroup{B}+ { + //printf("--> mgroup found!\n"); + lastMemberGroupContext = YY_START; + if (memberGroupId!=-1) + { + warn("Warning: ignoring nested mgroup command " + "at line %d of %s. Previous command was found at line %d\n", + yyLineNr,yyFileName,lastMemberGroupLine); + } + else + { + memberGroupId = newMemberGroupId(); + current->mGrpId = memberGroupId; + lastMemberGroupLine = yyLineNr; + } + BEGIN(GroupHeader); + } +<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")endmgroup/[^a-z_A-Z0-9] { + //printf("--> endmgroup found!\n"); + memberGroupId = -1; + current->mGrpId = -1; + } +<GroupHeader>[^\n]*/"\n" { + QCString header = ((QCString)yytext).stripWhiteSpace(); + memberGroupDict.insert(memberGroupId, + new MemberGroup(memberGroupId,header) + ); + BEGIN(lastMemberGroupContext); + } <Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")anchor{B}+ { lastAnchorContext = YY_START; sectionType=SectionInfo::Anchor; @@ -3216,6 +3365,7 @@ VAR [vV][aA][rR] } <ReadFormulaLong,ReadFormulaShort>. { formulaText+=*yytext; } <ExampleDoc,PageDoc,ClassDocBrief,ClassDoc>"*/" { + checkDocs(); if (YY_START==ClassDocBrief && lastBriefContext==Doc) { @@ -3432,6 +3582,7 @@ VAR [vV][aA][rR] BEGIN( lastDocContext ); } <Doc>"*/" { + checkDocs(); current->doc += "\n\n"; BEGIN( lastDocContext ); } @@ -3540,7 +3691,7 @@ void parseCompounds(Entry *rt) current->protection = protection = ce->protection; else if (ce->name.length()>0 && ce->name.at(0)=='@') // anonymous union current->protection = protection = ce->protection; - else // named struct or union + else // named struct, union, or interface current->protection = protection = Public ; sig = FALSE; slot = FALSE; @@ -3637,6 +3788,11 @@ void parseText(OutputList &ol,const QCString &txtString) scanYYrestart( scanYYin ); BEGIN( Text ); scanYYlex(); + if (memberGroupId!=-1) + { + warn("Warning: Missing \\endmgroup in file %s\n",yyFileName); + memberGroupId=-1; + } ol+=*outDoc; delete outDoc; return; @@ -3655,3 +3811,6 @@ void parseExample(OutputList &ol,const QCString &docString, } //---------------------------------------------------------------------------- +extern "C" { // some bogus code to keep the compiler happy + void scannerYYdummy() { yy_flex_realloc(0,0); } +} @@ -101,7 +101,7 @@ static void addNamespace(const char *name) static void addMember(const char *name,const char *anchor,const char *args) { - //printf("adding member %s\n",name); + //printf("adding member `%s' `%s'\n",name,anchor); if (cd || fd) { MemberNameDict *mnd=0; @@ -112,7 +112,8 @@ static void addMember(const char *name,const char *anchor,const char *args) md=new MemberDef(0,name,args,0,Public,Normal,FALSE,FALSE, MemberDef::Function,0,argList); delete argList; - md->setReference(anchor); + md->setAnchor(anchor); + md->setReference(tagName); if (cd) // member of a class { md->setMemberClass(cd); @@ -157,7 +158,7 @@ static void addMember(const char *name,const char *anchor,const char *args) %} -ID [a-z_A-Z][a-z_A-Z0-9]* +ID [a-z_A-Z0-9]+ FILE [a-z_A-Z0-9\.\-\+\:\\\/]+ SCOPE ({ID}"::")*{ID} diff --git a/src/translator.h b/src/translator.h index d5c4f67..e81ff92 100644 --- a/src/translator.h +++ b/src/translator.h @@ -42,148 +42,163 @@ class Translator { return "Reimplemented in"; } virtual QCString trIncludeFile() { return "Include File"; } + virtual QCString trGeneratedFrom(const char *s,bool single) + { + QCString result=(QCString)"The documentation for this"+s+ + " was generated from the following file"; + if (single) result+=":"; else result+="s:"; + return result; + } // end of obsolete functions //-------------------------------------------------------------------- + /*! returns the name of the package that is included by LaTeX */ virtual QCString latexBabelPackage() - // returns the name of the package that is included by LaTeX { return ""; } + /*! used in the compound documentation before a list of related functions. */ virtual QCString trRelatedFunctions() - // used in the compound documentation before a list of related functions. { return "Related Functions"; } + /*! subscript for the related functions. */ virtual QCString trRelatedSubscript() - // subscript for the related functions. { return "(Note that these are not member functions.)"; } + /*! header that is put before the detailed description of files, classes and namespaces. */ virtual QCString trDetailedDescription() - // header that is put before the detailed description of files, classes and namespaces. { return "Detailed Description"; } + /*! header that is put before the list of typedefs. */ virtual QCString trMemberTypedefDocumentation() - // header that is put before the list of typedefs. { return "Member Typedef Documentation"; } + /*! header that is put before the list of enumerations. */ virtual QCString trMemberEnumerationDocumentation() - // header that is put before the list of enumerations. { return "Member Enumeration Documentation"; } + /*! header that is put before the list of member functions. */ virtual QCString trMemberFunctionDocumentation() - // header that is put before the list of member functions. { return "Member Function Documentation"; } + /*! header that is put before the list of member attributes. */ virtual QCString trMemberDataDocumentation() - // header that is put before the list of member attributes. { return "Member Data Documentation"; } - - virtual QCString trGeneratedFrom(const char *s,bool single) - { // here s is one of " Class", " Struct" or " Union" - // single is true implies a single file - QCString result=(QCString)"The documentation for this"+s+ - " was generated from the following file"; - if (single) result+=":"; else result+="s:"; - return result; - } + /*! this is the text of a link put after brief descriptions. */ virtual QCString trMore() - // this is the text of a link put after brief descriptions. { return "More..."; } + /*! put in the class documentation */ virtual QCString trListOfAllMembers() - // put in the class documentation { return "List of all members."; } + /*! used as the title of the "list of all members" page of a class */ virtual QCString trMemberList() - // used as the title of the "list of all members" page of a class { return "Member List"; } + /*! this is the first part of a sentence that is followed by a class name */ virtual QCString trThisIsTheListOfAllMembers() - // this is the first part of a sentence that is followed by a class name { return "This is the complete list of members for "; } + + /*! this is the remainder of the sentence after the class name */ virtual QCString trIncludingInheritedMembers() - // this is the remainder of the sentence after the class name { return ", including all inherited members."; } + /*! this is put at the author sections at the bottom of man pages. + * parameter s is name of the project name. + */ virtual QCString trGeneratedAutomatically(const char *s) - // this is put at the author sections at the bottom of man pages. - // parameter s is name of the project name. { QCString result="Generated automatically by Doxygen"; if (s) result+=(QCString)" for "+s; result+=" from the source code."; return result; } + /*! put after an enum name in the list of all members */ virtual QCString trEnumName() - // put after an enum name in the list of all members { return "enum name"; } + /*! put after an enum value in the list of all members */ virtual QCString trEnumValue() - // put after an enum value in the list of all members { return "enum value"; } + /*! put after an undocumented member in the list of all members */ virtual QCString trDefinedIn() - // put after an undocumented member in the list of all members { return "defined in"; } + /*! put as in introduction in the verbatim header file of a class. + * parameter f is the name of the include file. + */ virtual QCString trVerbatimText(const char *f) - // put as in introduction in the verbatim header file of a class. - // parameter f is the name of the include file. { return (QCString)"This is the verbatim text of the "+f+" include file."; } // quick reference sections + + /*! This is put above each page as a link to the list of all groups of + * compounds or files (see the \group command). + */ virtual QCString trModules() - // This is put above each page as a link to the list of all groups of - // compounds or files (see the \group command). { return "Modules"; } + + /*! This is put above each page as a link to the class hierarchy */ virtual QCString trClassHierarchy() - // This is put above each page as a link to the class hierarchy { return "Class Hierarchy"; } + + /*! This is put above each page as a link to the list of annotated classes */ virtual QCString trCompoundList() - // This is put above each page as a link to the list of annotated classes { return "Compound List"; } + + /*! This is put above each page as a link to the list of documented files */ virtual QCString trFileList() - // This is put above each page as a link to the list of documented files { return "File List"; } + + /*! This is put above each page as a link to the list of all verbatim headers */ virtual QCString trHeaderFiles() - // This is put above each page as a link to the list of all verbatim headers { return "Header Files"; } + + /*! This is put above each page as a link to all members of compounds. */ virtual QCString trCompoundMembers() - // This is put above each page as a link to all members of compounds. { return "Compound Members"; } + + /*! This is put above each page as a link to all members of files. */ virtual QCString trFileMembers() - // This is put above each page as a link to all members of files. { return "File Members"; } + + /*! This is put above each page as a link to all related pages. */ virtual QCString trRelatedPages() - // This is put above each page as a link to all related pages. { return "Related Pages"; } + + /*! This is put above each page as a link to all examples. */ virtual QCString trExamples() - // This is put above each page as a link to all examples. { return "Examples"; } + + /*! This is put above each page as a link to the search engine. */ virtual QCString trSearch() - // This is put above each page as a link to the search engine. { return "Search"; } + /*! This is an introduction to the class hierarchy. */ virtual QCString trClassHierarchyDescription() - // This is an introduction to the class hierarchy. { return "This inheritance list is sorted roughly, " "but not completely, alphabetically:"; } + + /*! This is an introduction to the list with all files. */ virtual QCString trFileListDescription(bool extractAll) - // This is an introduction to the list with all files. { QCString result="Here is a list of all "; if (!extractAll) result+="documented "; result+="files with brief descriptions:"; return result; } + + /*! This is an introduction to the annotated compound list. */ virtual QCString trCompoundListDescription() - // This is an introduction to the annotated compound list { return "Here are the classes, structs and " "unions with brief descriptions:"; } + + /*! This is an introduction to the page with all class members. */ virtual QCString trCompoundMembersDescription(bool extractAll) - // This is an introduction to the page with all class members { QCString result="Here is a list of all "; if (!extractAll) result+="documented "; @@ -194,8 +209,9 @@ class Translator result+="the classes they belong to:"; return result; } + + /*! This is an introduction to the page with all file members. */ virtual QCString trFileMembersDescription(bool extractAll) - // This is an introduction to the page with all file members { QCString result="Here is a list of all "; if (!extractAll) result+="documented "; @@ -206,137 +222,197 @@ class Translator result+="the files they belong to:"; return result; } + + /*! This is an introduction to the page with the list of all header files. */ virtual QCString trHeaderFilesDescription() - // This is an introduction to the page with the list of all header files { return "Here are the header files that make up the API:"; } + + /*! This is an introduction to the page with the list of all examples */ virtual QCString trExamplesDescription() - // This is an introduction to the page with the list of all examples { return "Here is a list of all examples:"; } + + /*! This is an introduction to the page with the list of related pages */ virtual QCString trRelatedPagesDescription() - // This is an introduction to the page with the list of related pages { return "Here is a list of all related documentation pages:"; } + + /*! This is an introduction to the page with the list of class/file groups */ virtual QCString trModulesDescription() - // This is an introduction to the page with the list of class/file groups { return "Here is a list of all modules:"; } + + /*! This sentences is used in the annotated class/file lists if no brief + * description is given. + */ virtual QCString trNoDescriptionAvailable() - // This sentences is used in the annotated class/file lists if no brief - // description is given. { return "No description available"; } // index titles (the project name is prepended for these) + + + /*! This is used in HTML as the title of index.html. */ virtual QCString trDocumentation() - // This is used in HTML as the title of index.html. { return "Documentation"; } + + /*! This is used in LaTeX as the title of the chapter with the + * index of all groups. + */ virtual QCString trModuleIndex() - // This is used in LaTeX as the title of the chapter with the - // index of all groups. { return "Module Index"; } + + /*! This is used in LaTeX as the title of the chapter with the + * class hierarchy. + */ virtual QCString trHierarchicalIndex() - // This is used in LaTeX as the title of the chapter with the - // class hierarchy. { return "Hierarchical Index"; } + + /*! This is used in LaTeX as the title of the chapter with the + * annotated compound index. + */ virtual QCString trCompoundIndex() - // This is used in LaTeX as the title of the chapter with the - // annotated compound index { return "Compound Index"; } + + /*! This is used in LaTeX as the title of the chapter with the + * list of all files. + */ virtual QCString trFileIndex() - // This is used in LaTeX as the title of the chapter with the - // list of all files. { return "File Index"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all groups. + */ virtual QCString trModuleDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all groups. { return "Module Documentation"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all classes, structs and unions. + */ virtual QCString trClassDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all classes, structs and unions. { return "Class Documentation"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all files. + */ virtual QCString trFileDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all files. { return "File Documentation"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all examples. + */ virtual QCString trExampleDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all examples. { return "Example Documentation"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all related pages. + */ virtual QCString trPageDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all related pages. { return "Page Documentation"; } + + /*! This is used in LaTeX as the title of the document */ virtual QCString trReferenceManual() - // This is used in LaTeX as the title of the document { return "Reference Manual"; } + /*! This is used in the documentation of a file as a header before the + * list of defines + */ virtual QCString trDefines() - // This is used in the documentation of a file as a header before the - // list of defines { return "Defines"; } + + /*! This is used in the documentation of a file as a header before the + * list of function prototypes + */ virtual QCString trFuncProtos() - // This is used in the documentation of a file as a header before the - // list of function prototypes { return "Function Prototypes"; } + + /*! This is used in the documentation of a file as a header before the + * list of typedefs + */ virtual QCString trTypedefs() - // This is used in the documentation of a file as a header before the - // list of typedefs { return "Typedefs"; } + + /*! This is used in the documentation of a file as a header before the + * list of enumerations + */ virtual QCString trEnumerations() - // This is used in the documentation of a file as a header before the - // list of enumerations { return "Enumerations"; } + + /*! This is used in the documentation of a file as a header before the + * list of (global) functions + */ virtual QCString trFunctions() - // This is used in the documentation of a file as a header before the - // list of (global) functions { return "Functions"; } + + /*! This is used in the documentation of a file as a header before the + * list of (global) variables + */ virtual QCString trVariables() - // This is used in the documentation of a file as a header before the - // list of (global) variables { return "Variables"; } + + /*! This is used in the documentation of a file as a header before the + * list of (global) variables + */ virtual QCString trEnumerationValues() - // This is used in the documentation of a file as a header before the - // list of (global) variables { return "Enumeration values"; } + /*! This is used in man pages as the author section. */ virtual QCString trAuthor() - // This is used in man pages as the author section. { return "Author"; } + /*! This is used in the documentation of a file before the list of + * documentation blocks for defines + */ virtual QCString trDefineDocumentation() - // This is used in the documentation of a file before the list of - // documentation blocks for defines { return "Define Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for function prototypes + */ virtual QCString trFunctionPrototypeDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for function prototypes { return "Function Prototype Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for typedefs + */ virtual QCString trTypedefDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for typedefs { return "Typedef Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for enumeration types + */ virtual QCString trEnumerationTypeDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for enumeration types { return "Enumeration Type Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for enumeration values + */ virtual QCString trEnumerationValueDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for enumeration values { return "Enumeration Value Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for functions + */ virtual QCString trFunctionDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for functions { return "Function Documentation"; } + + /*! This is used in the documentation of a file/namespace before the list + * of documentation blocks for variables + */ virtual QCString trVariableDocumentation() - // This is used in the documentation of a file/namespace before the list - // of documentation blocks for variables { return "Variable Documentation"; } + + /*! This is used in the documentation of a file/namespace/group before + * the list of links to documented compounds + */ virtual QCString trCompounds() - // This is used in the documentation of a file/namespace/group before - // the list of links to documented compounds { return "Compounds"; } + + /*! This is used in the documentation of a group before the list of + * links to documented files + */ virtual QCString trFiles() - // This is used in the documentation of a group before the list of - // links to documented files { return "Files"; } + /*! This is used in the standard footer of each page and indicates when + * the page was generated + */ virtual QCString trGeneratedAt(const char *date,const char *projName) { QCString result=(QCString)"Generated at "+date; @@ -344,116 +420,137 @@ class Translator result+=(QCString)" by"; return result; } + /*! This is part of the sentence used in the standard footer of each page. + */ virtual QCString trWrittenBy() { return "written by"; } + /*! this text is put before a class diagram */ virtual QCString trClassDiagram(const char *clName) - // this text is put before a class diagram { return (QCString)"Class diagram for "+clName; } + /*! this text is generated when the \internal command is used. */ virtual QCString trForInternalUseOnly() - // this text is generated when the \internal command is used. { return "For internal use only."; } + + /*! this text is generated when the \reimp command is used. */ virtual QCString trReimplementedForInternalReasons() - // this text is generated when the \reimp command is used. { return "Reimplemented for internal reasons; the API is not affected."; } + + /*! this text is generated when the \warning command is used. */ virtual QCString trWarning() - // this text is generated when the \warning command is used. { return "Warning"; } + + /*! this text is generated when the \bug command is used. */ virtual QCString trBugsAndLimitations() - // this text is generated when the \bug command is used. { return "Bugs and limitations"; } + + /*! this text is generated when the \version command is used. */ virtual QCString trVersion() - // this text is generated when the \version command is used. { return "Version"; } + + /*! this text is generated when the \date command is used. */ virtual QCString trDate() - // this text is generated when the \date command is used. { return "Date"; } + + /*! this text is generated when the \author command is used. */ virtual QCString trAuthors() - // this text is generated when the \author command is used. { return "Author(s)"; } + + /*! this text is generated when the \return command is used. */ virtual QCString trReturns() - // this text is generated when the \return command is used. { return "Returns"; } + + /*! this text is generated when the \sa command is used. */ virtual QCString trSeeAlso() - // this text is generated when the \sa command is used. { return "See also"; } + + /*! this text is generated when the \param command is used. */ virtual QCString trParameters() - // this text is generated when the \param command is used. { return "Parameters"; } + + /*! this text is generated when the \exception command is used. */ virtual QCString trExceptions() - // this text is generated when the \exception command is used. { return "Exceptions"; } + /*! this text is used in the title page of a LaTeX document. */ virtual QCString trGeneratedBy() - // this text is used in the title page of a LaTeX document. { return "Generated by"; } // new since 0.49-990307 + /*! used as the title of page containing all the index of all namespaces. */ virtual QCString trNamespaceList() - // used as the title of page containing all the index of all namespaces. { return "Namespace List"; } + + /*! used as an introduction to the namespace list */ virtual QCString trNamespaceListDescription(bool extractAll) - // used as an introduction to the namespace list { QCString result="Here is a list of all "; if (!extractAll) result+="documented "; result+="namespaces with brief descriptions:"; return result; } + + /*! used in the class documentation as a header before the list of all + * friends of a class + */ virtual QCString trFriends() - // used in the class documentation as a header before the list of all - // friends of a class { return "Friends"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990405 ////////////////////////////////////////////////////////////////////////// + /*! used in the class documentation as a header before the list of all + * related classes + */ virtual QCString trRelatedFunctionDocumentation() - // used in the class documentation as a header before the list of all - // related classes { return "Friends And Related Function Documentation"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990425 ////////////////////////////////////////////////////////////////////////// + /*! used as the title of the HTML page of a class/struct/union */ virtual QCString trCompoundReference(const char *clName, ClassDef::CompoundType compType) - // used as the title of the HTML page of a class/struct/union { QCString result=(QCString)clName+" "; switch(compType) { - case ClassDef::Class: result+=" Class"; break; - case ClassDef::Struct: result+=" Struct"; break; - case ClassDef::Union: result+=" Union"; break; + case ClassDef::Class: result+=" Class"; break; + case ClassDef::Struct: result+=" Struct"; break; + case ClassDef::Union: result+=" Union"; break; + case ClassDef::Interface: result+=" Interface"; break; } result+=" Reference"; return result; } + + /*! used as the title of the HTML page of a file */ virtual QCString trFileReference(const char *fileName) - // used as the title of the HTML page of a file { QCString result=fileName; result+=" File Reference"; return result; } + + /*! used as the title of the HTML page of a namespace */ virtual QCString trNamespaceReference(const char *namespaceName) - // used as the title of the HTML page of a namespace { QCString result=namespaceName; result+=" Namespace Reference"; return result; } - // these are for the member sections of a class, struct or union + /*! \mgroup Class sections + * these are for the member sections of a class, struct or union + */ virtual QCString trPublicMembers() { return "Public Members"; } virtual QCString trPublicSlots() @@ -474,12 +571,13 @@ class Translator { return "Private Slots"; } virtual QCString trStaticPrivateMembers() { return "Static Private Members"; } - // end of member sections + /*! \endmgroup */ + /*! this function is used to produce a comma-separated list of items. + * use generateMarker(i) to indicate where item i should be put. + */ virtual QCString trWriteList(int numEntries) { - // this function is used to produce a comma-separated list of items. - // use generateMarker(i) to indicate where item i should be put. QCString result; int i; // the inherits list contain `numEntries' classes @@ -500,36 +598,44 @@ class Translator return result; } + /*! used in class documentation to produce a list of base classes, + * if class diagrams are disabled. + */ virtual QCString trInheritsList(int numEntries) - // used in class documentation to produce a list of base classes, - // if class diagrams are disabled. { return "Inherits "+trWriteList(numEntries)+"."; } + + /*! used in class documentation to produce a list of super classes, + * if class diagrams are disabled. + */ virtual QCString trInheritedByList(int numEntries) - // used in class documentation to produce a list of super classes, - // if class diagrams are disabled. { return "Inherited by "+trWriteList(numEntries)+"."; } + + /*! used in member documentation blocks to produce a list of + * members that are hidden by this one. + */ virtual QCString trReimplementedFromList(int numEntries) - // used in member documentation blocks to produce a list of - // members that are hidden by this one. { return "Reimplemented from "+trWriteList(numEntries)+"."; } + + /*! used in member documentation blocks to produce a list of + * all member that overwrite the implementation of this member. + */ virtual QCString trReimplementedInList(int numEntries) { - // used in member documentation blocks to produce a list of - // all member that overwrite the implementation of this member. return "Reimplemented in "+trWriteList(numEntries)+"."; } + /*! This is put above each page as a link to all members of namespaces. */ virtual QCString trNamespaceMembers() - // This is put above each page as a link to all members of namespaces. { return "Namespace Members"; } + + /*! This is an introduction to the page with all namespace members */ virtual QCString trNamespaceMemberDescription(bool extractAll) - // This is an introduction to the page with all namespace members { QCString result="Here is a list of all "; if (!extractAll) result+="documented "; @@ -540,23 +646,60 @@ class Translator result+="the namespaces they belong to:"; return result; } + /*! This is used in LaTeX as the title of the chapter with the + * index of all namespaces. + */ virtual QCString trNamespaceIndex() - // This is used in LaTeX as the title of the chapter with the - // index of all namespaces. { return "Namespace Index"; } + + /*! This is used in LaTeX as the title of the chapter containing + * the documentation of all namespaces. + */ virtual QCString trNamespaceDocumentation() - // This is used in LaTeX as the title of the chapter containing - // the documentation of all namespaces. { return "Namespace Documentation"; } ////////////////////////////////////////////////////////////////////////// // new since 0.49-990522 ////////////////////////////////////////////////////////////////////////// - // This is used in the documentation before the list of all - // namespaces in a file. + /*! This is used in the documentation before the list of all + * namespaces in a file. + */ virtual QCString trNamespaces() { return "Namespaces"; } + +////////////////////////////////////////////////////////////////////////// +// new since 0.49-990728 +////////////////////////////////////////////////////////////////////////// + + /*! This is put at the bottom of a class documentation page and is + * followed by a list of files that were used to generate the page. + */ + virtual QCString trGeneratedFromFiles(ClassDef::CompoundType compType, + bool single) + { // here s is one of " Class", " Struct" or " Union" + // single is true implies a single file + QCString result=(QCString)"The documentation for this "; + switch(compType) + { + case ClassDef::Class: result+="class"; break; + case ClassDef::Struct: result+="struct"; break; + case ClassDef::Union: result+="union"; break; + case ClassDef::Interface: result+="interface"; break; + } + result+="was generated from the following file"; + if (single) result+=":"; else result+="s:"; + return result; + } + + /*! This is in the (quick) index as a link to the alphabetical compound + * list. + */ + virtual QCString trAlphabeticalList() + { + return "Alphabetical List"; + } }; + #endif diff --git a/src/translator_de.h b/src/translator_de.h index 8cf43b6..8f17437 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -439,6 +439,7 @@ class TranslatorGerman : public Translator case ClassDef::Class: result+=" Klassen"; break; case ClassDef::Struct: result+=" Strukturen"; break; case ClassDef::Union: result+=" Varianten"; break; + case ClassDef::Interface: result+=" Interface"; break; } result+="referenz"; return result; diff --git a/src/translator_es.h b/src/translator_es.h index 9fcda7b..0aba0a8 100644 --- a/src/translator_es.h +++ b/src/translator_es.h @@ -286,6 +286,7 @@ class TranslatorSpanish : public Translator case ClassDef::Class: result+=" Clase"; break; case ClassDef::Struct: result+=" Estructura"; break; case ClassDef::Union: result+=" Unión"; break; + case ClassDef::Interface: result+=" Interface"; break; } result+=" Referencia"; return result; diff --git a/src/translator_it.h b/src/translator_it.h index e2f76dc..34d5660 100644 --- a/src/translator_it.h +++ b/src/translator_it.h @@ -299,6 +299,7 @@ class TranslatorItalian : public Translator case ClassDef::Class: result+=" classe"; break; case ClassDef::Struct: result+=" struct"; break; case ClassDef::Union: result+=" union"; break; + case ClassDef::Interface: result+=" interface"; break; } result+=" "+(QCString)clName; return result; diff --git a/src/translator_nl.h b/src/translator_nl.h index f5ceea9..4c105f1 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -269,6 +269,7 @@ class TranslatorDutch : public Translator case ClassDef::Class: result+=" Class"; break; case ClassDef::Struct: result+=" Struct"; break; case ClassDef::Union: result+=" Union"; break; + case ClassDef::Interface: result+=" Interface"; break; } result+=" Referentie"; return result; diff --git a/src/translator_se.h b/src/translator_se.h index 761d81d..2a04ff3 100644 --- a/src/translator_se.h +++ b/src/translator_se.h @@ -382,6 +382,7 @@ class TranslatorSwedish : public Translator case ClassDef::Class: result+=" Klass"; break; case ClassDef::Struct: result+=" Strukt"; break; case ClassDef::Union: result+=" Union"; break; + case ClassDef::Interface: result+=" Interface"; break; } result+="referens"; return result; diff --git a/src/util.cpp b/src/util.cpp index 49fdee5..d8a4772 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -29,6 +29,7 @@ #include "defargs.h" #include "language.h" #include "config.h" +#include "htmlhelp.h" // an inheritance tree of depth of 100000 should be enough for everyone :-) const int maxInheritanceDepth = 100000; @@ -58,6 +59,23 @@ QCString generateMarker(int id) return result; } +// strip part of the path if it matches +// one of the paths in the stripFromPath list +QCString stripFromPath(const QCString &path) +{ + const char *s=Config::stripFromPath.first(); + while (s) + { + QCString prefix = s; + if (path.left(prefix.length())==prefix) + { + return path.right(path.length()-prefix.length()); + } + s = Config::stripFromPath.next(); + } + return path; +} + // try to determine if this files is a source or a header file by looking // at the extension (5 variations are allowed in both upper and lower case) // If anyone knows or uses another extension please let me know :-) @@ -74,7 +92,8 @@ int guessSection(const char *name) n.right(3)==".hh" || n.right(4)==".hxx" || n.right(4)==".hpp" || - n.right(4)==".h++" + n.right(4)==".h++" || + n.right(4)==".idl" ) return Entry::HEADER_SEC; return 0; } @@ -140,64 +159,27 @@ QCString removeRedundantWhiteSpace(const QCString &s) return result; } -void writeTemplatePrefix(OutputList &ol,ArgumentList *al) + + +bool rightScopeMatch(const QCString &scope, const QCString &name) { - ol.docify("template<"); - Argument *a=al->first(); - while (a) - { - ol.docify(a->type); - ol.docify(a->name); - if (a->defval.length()!=0) - { - ol.docify(" = "); - ol.docify(a->defval); - } - a=al->next(); - if (a) ol.docify(", "); - } - ol.docify("> "); - bool latexEnabled = ol.isEnabled(OutputGenerator::Latex); - bool manEnabled = ol.isEnabled(OutputGenerator::Man); - if (latexEnabled) ol.disable(OutputGenerator::Latex); - if (manEnabled) ol.disable(OutputGenerator::Man); - ol.lineBreak(); - if (latexEnabled) ol.enable(OutputGenerator::Latex); - if (manEnabled) ol.enable(OutputGenerator::Man); + return (name==scope || // equal + (scope.right(name.length())==name && // substring + scope.at(scope.length()-name.length()-1)==':' // scope + ) + ); } -QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t) +bool leftScopeMatch(const QCString &scope, const QCString &name) { - //printf("addTemplateNames(%s)\n",s.data()); - QCString result; - QCString clRealName=n; - int p=0,i; - if ((i=clRealName.find('<'))!=-1) - { - clRealName=clRealName.left(i); // strip template specialization - } - while ((i=s.find(clRealName,p))!=-1) - { - result+=s.mid(p,i-p); - uint j=clRealName.length()+i; - if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j)))) - { // add template names - //printf("Adding %s+%s\n",clRealName.data(),t.data()); - result+=clRealName+t; - } - else - { // template names already present - //printf("Adding %s\n",clRealName.data()); - result+=clRealName; - } - p=i+clRealName.length(); - } - result+=s.right(s.length()-p); - //printf("result=%s\n",result.data()); - return result; + return (name==scope || // equal + (scope.left(name.length())==name && // substring + scope.at(name.length())==':' // scope + ) + ); } -static void linkifyText(OutputList &ol,const char *scName,const char *name,const char *text) +void linkifyText(OutputList &ol,const char *scName,const char *name,const char *text) { //printf("scope=`%s' name=`%s' Text: `%s'\n",scName,name,text); QRegExp regExp("[a-z_A-Z0-9:<>]+"); @@ -214,19 +196,20 @@ static void linkifyText(OutputList &ol,const char *scName,const char *name,const result.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); // get word from string QCString word=txtStr.mid(newIndex,matchLen); - ClassDef *cd=0; - FileDef *fd=0; - MemberDef *md=0; + ClassDef *cd=0; + FileDef *fd=0; + MemberDef *md=0; NamespaceDef *nd=0; QCString scopeName=scName; QCString searchName=name; //printf("word=`%s' scopeName=`%s' searchName=`%s'\n", - // word.data(),scopeName.data(),searchName.data()); + // word.data(),scopeName.data(),searchName.data() + // ); // check if `word' is a documented class name if (word.length()>0 && - word.right(searchName.length())!=searchName && - word!=scopeName.right(word.length()) + !rightScopeMatch(word,searchName) && + !rightScopeMatch(scopeName,word) ) { //printf("Searching...\n"); @@ -244,7 +227,7 @@ static void linkifyText(OutputList &ol,const char *scName,const char *name,const if ((cd=getClass(fullName))) { // add link to the result - if (cd->isVisible()) + if (cd->isLinkable()) { result.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,word); found=TRUE; @@ -264,25 +247,15 @@ static void linkifyText(OutputList &ol,const char *scName,const char *name,const if (!found && getDefs(scName,word,0,md,cd,fd,nd) && (md->isTypedef() || md->isEnumerate()) && - md->hasDocumentation() + md->isLinkable() ) { - if (cd && cd->isVisible()) // fullName is a member of cd - { - result.writeObjectLink(cd->getReference(), - cd->getOutputFileBase(),md->anchor(),word); - found=TRUE; - } - else if (nd && nd->hasDocumentation()) + Definition *d=0; + if (cd) d=cd; else if (nd) d=nd; else d=fd; + if (d && d->isLinkable()) { - result.writeObjectLink(nd->getReference(), - nd->getOutputFileBase(),md->anchor(),word); - found=TRUE; - } - else if (fd && fd->hasDocumentation()) // fullName is a global in file fd - { - result.writeObjectLink(fd->getReference(), - fd->getOutputFileBase(),md->anchor(),word); + result.writeObjectLink(d->getReference(),d->getOutputFileBase(), + md->anchor(),word); found=TRUE; } } @@ -305,70 +278,6 @@ static void linkifyText(OutputList &ol,const char *scName,const char *name,const ol+=result; } -static void writeDefArgumentList(OutputList &ol,ClassDef *cd, - const QCString &scopeName,MemberDef *md) -{ - ArgumentList *argList=md->argumentList(); - if (argList==0) return; // member has no function like argument list - ol.docify(" ("); // start argument list - Argument *a=argList->first(); - QCString cName; - if (cd && cd->templateArguments()) - { - cName=cd->getTemplateNameString(); - } - while (a) - { - QRegExp re(")("); - int vp; - if ((vp=a->type.find(re))!=-1) // argument type is a function pointer - { - QCString n=a->type.left(vp); - if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); - linkifyText(ol,scopeName,md->name(),n); - } - else // non-function pointer type - { - QCString n=a->type; - if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); - linkifyText(ol,scopeName,md->name(),n); - } - if (a->name.length()>0) // argument has a name - { - ol.docify(" "); - ol.disable(OutputGenerator::Man); - ol.startEmphasis(); - ol.enable(OutputGenerator::Man); - ol.docify(a->name); - ol.disable(OutputGenerator::Man); - ol.endEmphasis(); - ol.enable(OutputGenerator::Man); - } - if (vp!=-1) // write the part of the argument type - // that comes after the name - { - linkifyText(ol,scopeName,md->name(),a->type.right(a->type.length()-vp)); - } - if (a->defval.length()>0) // write the default value - { - QCString n=a->defval; - if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName); - ol.docify(" = "); - linkifyText(ol,scopeName,md->name(),n); - } - a=argList->next(); - if (a) ol.docify(", "); // there are more arguments - } - ol.docify(")"); // end argument list - if (argList->constSpecifier) - { - ol.docify(" const"); - } - if (argList->volatileSpecifier) - { - ol.docify(" volatile"); - } -} void writeExample(OutputList &ol,ExampleList *el) { @@ -409,37 +318,53 @@ QCString argListToString(ArgumentList *al) if (al->volatileSpecifier) result+=" volatile"; return result; } - -static void writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd, - FileDef *fd,MemberDef *md,const char *name) -{ - if (nd) - ol.writeObjectLink(nd->getReference(),nd->getOutputFileBase(), - md->anchor(),name); - else if (fd) - ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(), - md->anchor(),name); - else - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(), - md->anchor(),name); -} -static void warnForUndocumentedMember(MemberDef *md) +//QCString tempArgListToString(ArgumentList *al) +//{ +// QCString result; +// if (al==0) return result; +// Argument *a=al->first(); +// result+="<"; +// while (a) +// { +// int ni=a->type.findRev(' '); +// if (ni!=-1) +// result+=a->type.right(a->type.length()-ni-1); +// else +// result+=a->type; +// a = al->next(); +// if (a) result+=","; +// } +// result+=">"; +// return result; +//} + +QCString tempArgListToString(ArgumentList *al) { - ClassDef *cd=md->memberClass(); - FileDef *fd=md->getFileDef(); - if (cd) - { - if (!md->hasDocumentation() && md->name() && md->name()[0]!='@') - warn("Warning: Member %s of class %s is not documented\n", - md->name().data(),cd->name().data()); - } - else if (fd) + QCString result; + if (!al || al->count()==0) return result; + result="<"; + Argument *a=al->first(); + while (a) { - if (!md->hasDocumentation() && md->name() && md->name()[0]!='@') - warn("Warning: Member %s of file %s is not documented\n", - md->name().data(),fd->name().data()); + if (a->name.length()>0) // add template argument name + { + result+=a->name; + } + else // extract name from type + { + int i=a->type.length()-1; + while (i>=0 && isId(a->type.at(i))) i--; + if (i>0) + { + result+=a->type.right(a->type.length()-i-1); + } + } + a=al->next(); + if (a) result+=", "; } + result+=">"; + return result; } static bool manIsEnabled; @@ -489,6 +414,13 @@ void writeQuickLinks(OutputList &ol,bool compact,bool ext) } if (annotatedClasses>0) { + if (Config::alphaIndexFlag) + { + if (!compact) ol.writeListItem(); + ol.startQuickIndexItem(extLink,absPath+"classes.html"); + parseText(ol,theTranslator->trAlphabeticalList()); + ol.endQuickIndexItem(); + } if (!compact) ol.writeListItem(); ol.startQuickIndexItem(extLink,absPath+"annotated.html"); parseText(ol,theTranslator->trCompoundList()); @@ -501,7 +433,7 @@ void writeQuickLinks(OutputList &ol,bool compact,bool ext) parseText(ol,theTranslator->trFileList()); ol.endQuickIndexItem(); } - if (includeFiles.count()>0 && Config::verbatimHeaderFlag) + if (documentedIncludeFiles>0 && Config::verbatimHeaderFlag) { if (!compact) ol.writeListItem(); ol.startQuickIndexItem(extLink,absPath+"headers.html"); @@ -594,427 +526,6 @@ void endFile(OutputList &ol,bool external) ol.endFile(); } - -static void writeMemberDef(OutputList &ol, ClassDef *cd, NamespaceDef *nd, - FileDef *fd, MemberDef *md) -{ - int i,l; - bool hasDocs=md->hasDocumentation(); - if ((!hasDocs && Config::hideMemberFlag) || - (Config::hideMemberFlag && - md->documentation().isEmpty() && - !Config::briefMemDescFlag && - !Config::repeatBriefFlag - ) - ) return; - QCString type=md->typeString(); - QRegExp r("@[0-9]+"); - if ((i=r.match(type,0,&l))==-1 || !md->enumUsed()) - { - // strip `static' keyword from type - if (type.left(7)=="static ") type=type.right(type.length()-7); - // strip `friend' keyword from type - if (type.left(7)=="friend ") type=type.right(type.length()-7); - - if (Config::genTagFile.length()>0) - { - tagFile << md->name() << " " << md->anchor() << " \"" - << md->argsString() << "\"\n"; - } - - QCString cname; - if (cd) cname=cd->name(); - else if (nd) cname=nd->name(); - else if (fd) cname=fd->name(); - - ol.startMemberItem(); - // If there is no detailed description we need to write the anchor here. - bool detailsVisible = md->detailsAreVisible(); - if (!detailsVisible && !Config::extractAllFlag) - { - QCString doxyName=md->name().copy(); - if (!cname.isEmpty()) doxyName.prepend(cname+"::"); - ol.writeDoxyAnchor(cname,md->anchor(),doxyName); - ol.addToIndex(md->name(),cname); - ol.addToIndex(cname,md->name()); - ol.docify("\n"); - } - else if (!detailsVisible) // when extractAll it true we have to write - // a index reference and label in LaTeX because - // detailed section not shown in LaTeX - { - ol.addToIndex(md->name(),cname); - ol.addToIndex(cname,md->name()); - ol.writeLatexLabel(cname,md->anchor()); - } - - // write type - if (i!=-1) - { - QCString newType = type.left(i) + " { ... } " + - type.right(type.length()-i-l); - type = newType; - //ol.docify(type); - linkifyText(ol,cname,md->name(),type); - } - else - { - //ol.docify(type); - linkifyText(ol,cname,md->name(),type); - } - QCString name=md->name().copy(); - bool htmlOn = ol.isEnabled(OutputGenerator::Html); - if (htmlOn && Config::htmlAlignMemberFlag && type.length()>0) - { - ol.disable(OutputGenerator::Html); - } - if (!type.isEmpty()) ol.docify(" "); - if (htmlOn) - { - ol.enable(OutputGenerator::Html); - } - - ol.insertMemberAlign(); - - // write name - if (md->hasDocumentation()) - { - //printf("writeLink %s->%d\n",name.data(),md->hasDocumentation()); - writeLink(ol,cd,nd,fd,md,name); - } - else // there is a brief member description and brief member - // descriptions are enabled or there is no detailed description. - { - ol.writeBoldString(name); - } - - if (md->argsString()) - { - ol.writeString(" "); - //ol.docify(md->argsString()); - linkifyText(ol,cname,md->name(),md->argsString()); - } - - if (md->excpString()) - { - ol.writeString(" "); - ol.docify(md->excpString()); - } - - ol.endMemberItem(); - - // write brief description - if (!md->briefDescription().isEmpty() && Config::briefMemDescFlag) - { - ol.startMemberDescription(); - parseDoc(ol,cname,md->name(),md->briefDescription()); - //if (!md->documentation().isEmpty()) - //{ - // ol.disableAllBut(OutputGenerator::Html); - // ol.endEmphasis(); - // ol.docify(" "); - // ol.startTextLink(0,md->anchor()); - // parseText(ol,theTranslator->trMore()); - // ol.endTextLink(); - // ol.startEmphasis(); - // ol.enableAll(); - //} - ol.endMemberDescription(); - ol.newParagraph(); - } - } - warnForUndocumentedMember(md); -} - - -// write a list in HTML of all members of a certain category -// cd!=0 => ml is a list of class members -// fd!=0 => ml is a list of file `members' -void writeMemberDecs(OutputList &ol,ClassDef *cd,NamespaceDef *nd, FileDef *fd, - const char *title, const char *subtitle,MemberList *ml) -{ - ml->countDecMembers(); - if (ml->totalCount()==0) return; - if (title) - { - ol.startMemberHeader(); - parseText(ol,title); - ol.endMemberHeader(); - } - if (subtitle) - { - ol.startMemberSubtitle(); - parseText(ol,subtitle); - ol.endMemberSubtitle(); - } - - if (!fd && !nd) ol.startMemberList(); - MemberDef *md; - - if (fd && ml->defineCount()>0) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trDefines()); - ol.endMemberHeader(); - ol.startMemberList(); - MemberListIterator mli(*ml); - for ( ; (md=mli.current()); ++mli ) - { - if (md->isDefine() && - (md->argsString() || md->hasDocumentation() || Config::extractAllFlag) - ) - writeMemberDef(ol,cd,nd,fd,md); - } - ol.endMemberList(); - } - - if ((fd || nd) && ml->protoCount()>0) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trFuncProtos()); - ol.startMemberList(); - MemberListIterator mli(*ml); - for ( ; (md=mli.current()); ++mli ) - { - if (md->isPrototype()) writeMemberDef(ol,cd,nd,fd,md); - } - ol.endMemberList(); - } - - if (ml->typedefCount()>0) - { - if (fd || nd) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trTypedefs()); - ol.endMemberHeader(); - //ol.writeMemberHeader("Typedefs"); - ol.startMemberList(); - } - MemberListIterator mli(*ml); - for ( ; (md=mli.current()) ; ++mli ) - { - if (md->isTypedef()) writeMemberDef(ol,cd,nd,fd,md); - } - if (fd || nd) ol.endMemberList(); - } - - // write enums - if (ml->enumCount()>0) - { - if (fd || nd) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trEnumerations()); - ol.endMemberHeader(); - ol.startMemberList(); - } - MemberListIterator mli(*ml); - for ( ; (md=mli.current()) ; ++mli ) - { - /*bool hasDocs=md->hasDocumentation();*/ - QCString type=md->typeString(); - type=type.stripWhiteSpace(); - if (md->isEnumerate() /*&& (hasDocs || !Config::hideMemberFlag)*/) - { - if (!Config::hideMemberFlag || // do not hide undocumented members or - !md->documentation().isEmpty() || // member has detailed descr. or - md->hasDocumentedEnumValues() || // member has documented enum vales. - Config::briefMemDescFlag || // brief descr. is shown or - Config::repeatBriefFlag // brief descr. is repeated. - ) - { - OutputList typeDecl(&ol); - QCString name=md->name().copy(); - int i=name.findRev("::"); - if (i!=-1) name=name.right(name.length()-i-2); // strip scope - if (name[0]!='@') // not an anonymous enum - { - //if (Config::extractAllFlag || - // (md->briefDescription().isEmpty() || !Config::briefMemDescFlag) && - // (!md->documentation().isEmpty() || md->hasDocumentedEnumValues() || - // (!md->briefDescription().isEmpty() && - // !Config::briefMemDescFlag && - // Config::repeatBriefFlag - // ) - // ) - // ) - if (md->hasDocumentation() || md->hasDocumentedEnumValues()) - { - if (Config::genTagFile.length()>0) - tagFile << md->name() << " " << md->anchor() - << " \"" << md->argsString() << "\""; - writeLink(typeDecl,cd,nd,fd,md,name); - } - else - { - typeDecl.writeBoldString(name); - } - typeDecl.writeChar(' '); - } - - typeDecl.docify("{ "); - QList<MemberDef> *fmdl=md->enumFieldList(); - if (fmdl) - { - MemberDef *fmd=fmdl->first(); - while (fmd) - { - if (fmd->hasDocumentation()) - { - if (Config::genTagFile.length()>0) - tagFile << fmd->name() << " " << fmd->anchor() - << " \"" << fmd->argsString() << "\""; - writeLink(typeDecl,cd,nd,fd,fmd,fmd->name()); - } - else - typeDecl.writeBoldString(fmd->name()); - fmd=fmdl->next(); - if (fmd) typeDecl.writeString(", "); - typeDecl.disable(OutputGenerator::Man); - typeDecl.writeString("\n"); // to prevent too long lines in LaTeX - typeDecl.enable(OutputGenerator::Man); - } - } - typeDecl.docify(" }"); - md->setEnumDecl(typeDecl); - int enumVars=0; - MemberListIterator vmli(*ml); - MemberDef *vmd; - if (name[0]=='@') // anonymous enum => append variables - { - for ( ; (vmd=vmli.current()) ; ++vmli) - { - QCString vtype=vmd->typeString(); - if ((vtype.find(name))!=-1) enumVars++; - } - } - if (enumVars==0) // no variable of this enum type - { - ol.startMemberItem(); - ol.writeString("enum "); - ol.insertMemberAlign(); - ol+=typeDecl; - ol.endMemberItem(); - //QCString brief=md->briefDescription(); - //brief=brief.stripWhiteSpace(); - if (!md->briefDescription().isEmpty() && Config::briefMemDescFlag) - { - ol.startMemberDescription(); - parseDoc(ol,cd?cd->name().data():0, - md->name().data(),md->briefDescription()); - //if (!md->documentation().isEmpty() || md->hasDocumentedEnumValues()) - //{ - // ol.disableAllBut(OutputGenerator::Html); - // ol.endEmphasis(); - // ol.docify(" "); - // ol.startTextLink(0,md->anchor()); - // //ol.writeObjectLink(0,0,md->anchor()," More..."); - // parseText(ol,theTranslator->trMore()); - // ol.endTextLink(); - // ol.startEmphasis(); - // ol.enableAll(); - //} - ol.endMemberDescription(); - ol.disable(OutputGenerator::Man); - ol.newParagraph(); - ol.enable(OutputGenerator::Man); - } - } - warnForUndocumentedMember(md); - } - } // md->isEnumerate() - } // enum loop - if (fd || nd) ol.endMemberList(); - } // write enums - - // write functions - if (ml->funcCount()>0) - { - if (fd || nd) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trFunctions()); - ol.endMemberHeader(); - ol.startMemberList(); - } - MemberListIterator mli(*ml); - for ( ; (md=mli.current()) ; ++mli ) - { - if ( md->isFunction() || md->isSignal() || - md->isSlot()) - writeMemberDef(ol,cd,nd,fd,md); - } - if (fd || nd) ol.endMemberList(); - } - - if (ml->friendCount()>0) - { - MemberListIterator mli(*ml); - for ( ; (md=mli.current()) ; ++mli ) - { - if ( md->isFriend()) - { - QCString type=md->typeString(); - //printf("Friend: type=%s name=%s\n",type.data(),md->name().data()); - if (md->hasDocumentation() && type!="friend class") - { - writeMemberDef(ol,cd,nd,fd,md); - } - else // friend is undocumented as a member but it is a class, - // so generate a link to the class if that is documented. - { - ClassDef *cd=getClass(md->name()); - if (md->hasDocumentation()) // friend is documented - { - ol.startMemberItem(); - ol.docify("class "); - ol.insertMemberAlign(); - ol.writeObjectLink(0,0,md->anchor(),md->name()); - ol.endMemberItem(); - } - else if (cd && cd->isVisibleExt()) // class is documented - { - ol.startMemberItem(); - ol.docify("class "); - ol.insertMemberAlign(); - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->name()); - ol.endMemberItem(); - } - else if (!Config::hideMemberFlag) // no documentation - { - ol.startMemberItem(); - ol.docify("class "); - ol.insertMemberAlign(); - ol.writeBoldString(md->name()); - ol.endMemberItem(); - } - } - } - } - } - - // write variables - if (ml->varCount()>0) - { - if (fd || nd) - { - ol.startMemberHeader(); - parseText(ol,theTranslator->trVariables()); - ol.endMemberHeader(); - ol.startMemberList(); - } - MemberListIterator mli(*ml); - for ( ; (md=mli.current()) ; ++mli ) - { - if (md->isVariable()) writeMemberDef(ol,cd,nd,fd,md); - } - if (fd || nd) ol.endMemberList(); - } - - if (!fd && !nd) { ol.endMemberList(); ol.writeChar('\n'); } -} - // compute the HTML anchors for a list of members void setAnchors(char id,MemberList *ml) { @@ -1030,397 +541,6 @@ void setAnchors(char id,MemberList *ml) } } -void writeMemberDocs(OutputList &ol,MemberList *ml,const char *scopeName, - MemberDef::MemberType m) -{ - MemberListIterator mli(*ml); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) - { - bool hasDocs = md->detailsAreVisible(); - // !md->documentation().isEmpty() || // member has a detailed description - // (md->memberType()==MemberDef::Enumeration && // or member is an enum and - // md->hasDocumentedEnumValues() // one of its values is documented - // ) || // or - // (!md->briefDescription().isEmpty() && // member has brief description and - // !Config::briefMemDescFlag && // brief description not shown earlier and - // Config::repeatBriefFlag // brief description should be repeated. - // ); - if (md->memberType()==m && // filter member type - (Config::extractAllFlag || hasDocs) - ) - { - if (Config::extractAllFlag && !hasDocs) - { - ol.disable(OutputGenerator::Latex); // Latex cannot insert a pagebreak - // if there are a lot of empty sections, - // so we disable LaTeX for all empty - // sections even if Config::extractAllFlag is enabled - } - QCString cname; - NamespaceDef *nd=md->getNamespace(); - ClassDef *cd=md->memberClass(); - FileDef *fd=md->getFileDef(); - if (cd) cname=cd->name(); - else if (nd) cname=nd->name(); - else if (fd) cname=fd->name(); - // get member name - QCString doxyName=md->name().copy(); - // prepend scope if there is any - if (scopeName) doxyName.prepend((QCString)scopeName+"::"); - - QCString def = md->definition(); - if (md->isEnumerate()) def.prepend("enum "); - MemberDef *smd; - if (md->isEnumValue() && def[0]=='@') def = def.right(def.length()-2); - int i=0,l,dummy; - QRegExp r("@[0-9]+"); - if (md->isEnumerate() && r.match(def,0,&l)!=-1) continue; - if (md->isEnumValue() && (smd = md->getEnumScope()) - && r.match(smd->name(),0,&dummy)==-1) continue; - if ((md->isVariable() || md->isTypedef()) && (i=r.match(def,0,&l))!=-1) - { - // find enum type an insert it in the definition - MemberListIterator vmli(*ml); - MemberDef *vmd; - bool found=FALSE; - for ( ; (vmd=vmli.current()) && !found ; ++vmli) - { - if (vmd->isEnumerate() && def.mid(i,l)==vmd->name()) - { - ol.startMemberDoc(cname,md->name(),md->anchor()); - ol.writeDoxyAnchor(cname,md->anchor(),doxyName); - linkifyText(ol,scopeName,md->name(),def.left(i)); - ol+=*vmd->enumDecl(); - linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l)); - found=TRUE; - } - } - if (!found) // anonymous compound - { - ol.startMemberDoc(cname,md->name(),md->anchor()); - ol.writeDoxyAnchor(cname,md->anchor(),doxyName); - linkifyText(ol,scopeName,md->name(),def.left(i)); - ol.docify(" { ... } "); - linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l)); - } - } - else - { - ol.startMemberDoc(cname,md->name(),md->anchor()); - ol.writeDoxyAnchor(cname,md->anchor(),doxyName); - ArgumentList *al=0; - if (cd && (!md->isRelated() || !md->templateArguments()) && - ((al=md->scopeTemplateArguments()) || (al=cd->templateArguments())) - ) // class template prefix - { - writeTemplatePrefix(ol,al); - } - if (al && md->templateArguments()) ol.docify(" "); - al=md->templateArguments(); - if (al) // function template prefix - { - writeTemplatePrefix(ol,al); - } - if (cd && md->scopeTemplateArguments()) - { - def=addTemplateNames(def,cd->name(),md->getScopeTemplateNameString()); - } - else if (cd && cd->templateArguments()) - { - // add template name lists to all occurrences of the class name. - def=addTemplateNames(def,cd->name(),cd->getTemplateNameString()); - } - linkifyText(ol,scopeName,md->name(),def); - writeDefArgumentList(ol,cd,scopeName,md); - if (md->excpString()) - { - ol.docify(" "); - linkifyText(ol,scopeName,md->name(),md->excpString()); - } - } - - Specifier virt=md->virtualness(); - MemberDef *rmd=md->reimplements(); - while (rmd && virt==Normal) - { - virt = rmd->virtualness()==Normal ? Normal : Virtual; - rmd = rmd->reimplements(); - } - - if (md->isStatic() || md->protection()!=Public || - virt!=Normal || md->isSignal() || md->isFriend() || - md->isRelated() || md->isSlot() - ) - { - // write the member specifier list - ol.writeLatexSpacing(); - ol.startTypewriter(); - ol.docify(" ["); - QStrList sl; - if (md->isFriend()) sl.append("friend"); - else if (md->isRelated()) sl.append("related"); - else - { - if (md->isStatic()) sl.append("static"); - if (md->protection()==Protected) sl.append("protected"); - else if (md->protection()==Private) sl.append("private"); - if (virt==Virtual) sl.append("virtual"); - else if (virt==Pure) sl.append("pure virtual"); - if (md->isSignal()) sl.append("signal"); - if (md->isSlot()) sl.append("slot"); - } - const char *s=sl.first(); - while (s) - { - ol.docify(s); - s=sl.next(); - if (s) ol.docify(", "); - } - ol.docify("]"); - ol.endTypewriter(); - } - ol.endMemberDoc(); - ol.startIndent(); - ol.newParagraph(); - - if (!md->briefDescription().isEmpty() && - (Config::repeatBriefFlag || - (!Config::briefMemDescFlag && md->documentation().isEmpty()) - ) - ) - { - parseDoc(ol,scopeName,md->name(),md->briefDescription()); - ol.newParagraph(); - } - if (!md->documentation().isEmpty()) - { - parseDoc(ol,scopeName,md->name(),md->documentation()+"\n"); - } - if (!md->bodyCode().isEmpty()) - { - ol.startCodeFragment(); - parseCode(ol,scopeName,md->bodyCode(),FALSE,0); - ol.endCodeFragment(); - } - - if (md->isEnumerate()) - { - bool first=TRUE; - MemberList *fmdl=md->enumFieldList(); - if (fmdl) - { - MemberDef *fmd=fmdl->first(); - while (fmd) - { - if (fmd->hasDocumentation()) - { - if (first) - { - ol.newParagraph(); - ol.startBold(); - parseText(ol,theTranslator->trEnumerationValues()); - //ol.writeBoldString("Enumeration values:"); - ol.docify(":"); - ol.endBold(); - ol.startItemList(); - } - ol.writeDoxyAnchor(cname,fmd->anchor(),fmd->name()); - ol.addToIndex(fmd->name(),cname); - ol.addToIndex(cname,fmd->name()); - ol.writeListItem(); - first=FALSE; - ol.startBold(); - ol.docify(fmd->name()); - ol.endBold(); - ol.newParagraph(); - - if (!fmd->briefDescription().isEmpty()) - { - parseDoc(ol,scopeName,fmd->name(),fmd->briefDescription()); - ol.newParagraph(); - } - if (!fmd->documentation().isEmpty()) - { - parseDoc(ol,scopeName,fmd->name(),fmd->documentation()+"\n"); - } - ol.disable(OutputGenerator::Man); - ol.newParagraph(); - ol.enable(OutputGenerator::Man); - } - fmd=fmdl->next(); - } - } - if (!first) { ol.endItemList(); ol.writeChar('\n'); } - } - - MemberDef *bmd=md->reimplements(); - ClassDef *bcd=0; - if (bmd && (bcd=bmd->memberClass())) - { - if (virt!=Normal) // search for virtual member of the deepest base class - { - MemberDef *lastBmd=bmd; - while (lastBmd) - { - ClassDef *lastBcd = lastBmd->memberClass(); - if (lastBmd->virtualness()!=Normal && - lastBmd->hasDocumentation() && - (lastBmd->protection()!=Private || Config::extractPrivateFlag) && - lastBcd->hasDocumentation() && - (lastBcd->protection()!=Private || Config::extractPrivateFlag) - ) { bmd=lastBmd; bcd=lastBcd; } - lastBmd=lastBmd->reimplements(); - } - } - // write class that contains a member that is reimplemented by this one - if (bcd->hasDocumentation() || bcd->isReference()) - { - ol.newParagraph(); - - QCString reimplFromLine = theTranslator->trReimplementedFromList(1); - int markerPos = reimplFromLine.find("@0"); - if (markerPos!=-1) // should always pass this. - { - parseText(ol,reimplFromLine.left(markerPos)); //text left from marker - if (bmd->hasDocumentation() && - (bmd->protection()!=Private || Config::extractPrivateFlag) - ) // replace marker with link - { - ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), - bmd->anchor(),bcd->name()); - if ( - !bcd->isReference() && - //(bcd->hasDocumentation() || !Config::hideClassFlag) && - //(bcd->protection()!=Private || Config::extractPrivateFlag) - bcd->isVisible() - /*&& bmd->detailsAreVisible()*/ - ) ol.writePageRef(bcd->name(),bmd->anchor()); - } - else - { - ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), - 0,bcd->name()); - if ( - !bcd->isReference() && - //(bcd->hasDocumentation() || !Config::hideClassFlag) && - //(bcd->protection()!=Private || Config::extractPrivateFlag) - bcd->isVisible() - ) ol.writePageRef(bcd->name(),0); - } - parseText(ol,reimplFromLine.right( - reimplFromLine.length()-markerPos-2)); // text right from marker - - } - else - { - err("Error: translation error: no marker in trReimplementsFromList()\n"); - } - } - - //ol.writeString("."); - } - MemberList *bml=md->reimplementedBy(); - if (bml) - { - MemberListIterator mli(*bml); - MemberDef *bmd=0; - uint count=0; - ClassDef *bcd=0; - for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->memberClass());++mli) - { - // count the members that directly inherit from md and for - // which the member and class are visible in the docs. - if (bmd->hasDocumentation() && - (bmd->protection()!=Private || Config::extractPrivateFlag) && - bcd->hasDocumentation() && - (bcd->protection()!=Private || Config::extractPrivateFlag) - ) count++; - } - if (count>0) - { - mli.toFirst(); - // write the list of classes that overwrite this member - ol.newParagraph(); - //parseText(ol,theTranslator->trReimplementedIn()); - //ol.writeString("Reimplemented in "); - //ol.docify(" "); - - QCString reimplInLine = - theTranslator->trReimplementedInList(count); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in reimplInLine with links to the classes - while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1) - { - parseText(ol,reimplInLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - //bmd=bml->at(entryIndex); - - count=0; - // find the entryIndex-th documented entry in the inheritance list. - for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->memberClass());++mli) - { - if (bmd->hasDocumentation() && - (bmd->protection()!=Private || Config::extractPrivateFlag) && - bcd->hasDocumentation() && - (bcd->protection()!=Private || Config::extractPrivateFlag) - ) - { - if (count==entryIndex) break; - count++; - } - } - - if (ok && bcd && bmd) // write link for marker - { - //if (bmd->hasDocumentation() && - // (bmd->protection()!=Private || Config::extractPrivateFlag) - // ) - //{ - ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), - bmd->anchor(),bcd->name()); - if (!bcd->isReference() && bcd->isVisible()) - ol.writePageRef(bcd->name(),bmd->anchor()); - //} - //else - //{ - // ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(), - // 0,bcd->name()); - // if (!bcd->isReference() && bcd->isVisible()) - // ol.writePageRef(bcd->name(),0); - //} - } - ++mli; - index=newIndex+matchLen; - } - parseText(ol,reimplInLine.right(reimplInLine.length()-index)); - - } - } - // write the list of examples that use this member - if (md->hasExamples()) - { - ol.startDescList(); - ol.startBold(); - parseText(ol,theTranslator->trExamples()+": "); - //ol.writeBoldString("Examples: "); - ol.endBold(); - ol.endDescTitle(); - ol.writeDescItem(); - writeExample(ol,md->getExampleList()); - //ol.endDescItem(); - ol.endDescList(); - } - ol.endIndent(); - // enable LaTeX again - if (Config::extractAllFlag && !hasDocs) ol.enable(OutputGenerator::Latex); - - } - } -} - //---------------------------------------------------------------------------- // read a file with `name' to a string. @@ -1607,6 +727,13 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, QCString className=cl; QCString namespaceName=ns; + // strip template specialization from class name if present + int til=className.find('<'),tir=className.find('>'); + if (til!=-1 && tir!=-1 && tir>til) + { + className=className.left(til)+className.right(className.length()-tir-1); + } + //printf("matchArguments(%s,%s) className=%s namespaceName=%s\n", // srcAl ? argListToString(srcAl).data() : "", // dstAl ? argListToString(dstAl).data() : "", @@ -1616,6 +743,8 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, { return srcAl==dstAl; // at least one of the members is not a function } + + // handle special case with void argument if ( srcAl->count()==0 && dstAl->count()==1 && dstAl->getFirst()->type=="void" ) { // special case for finding match between func() and func(void) @@ -1632,9 +761,9 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, dstAl->append(a); return TRUE; } + if (srcAl->count() != dstAl->count()) { - //printf("Different number of arguments!\n"); return FALSE; // different number of arguments -> no match } if (srcAl->constSpecifier != dstAl->constSpecifier) @@ -1683,6 +812,7 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, srcAType=trimScope(namespaceName,srcAType); dstAType=trimScope(namespaceName,dstAType); } + //printf("srcAType=%s dstAType=%s\n",srcAType.data(),dstAType.data()); //printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data()); uint srcPos=0,dstPos=0; @@ -1796,8 +926,10 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, else // without scopes the names match exactly { } + return TRUE; } - else if (srcA->name.length()==0 && dstA->name.length()==0) + //printf("match exactly\n"); + if (srcA->name.isEmpty() && dstA->name.isEmpty()) // arguments match exactly but no name -> // see if we can find the name { @@ -1812,6 +944,14 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl, dstA->type=dstAType.left(i+1).stripWhiteSpace(); } } + else if (!dstA->name.isEmpty()) + { + srcA->name=dstA->name.copy(); + } + else if (!srcA->name.isEmpty()) + { + dstA->name=srcA->name.copy(); + } } //printf("Match found!\n"); return TRUE; // all arguments match @@ -1964,7 +1104,7 @@ bool getDefs(const QCString &scName,const QCString &memberName, ClassDef *fcd=0; if ((fcd=getClass(className)) && // is it a documented class - fcd->isVisibleExt() + fcd->isLinkable() ) { //printf(" Found fcd=%p\n",fcd); @@ -1972,8 +1112,9 @@ bool getDefs(const QCString &scName,const QCString &memberName, int mdist=maxInheritanceDepth; while (mmd) { - if ((mmd->protection()!=Private || Config::extractPrivateFlag) && - mmd->hasDocumentation() + if (//(mmd->protection()!=Private || Config::extractPrivateFlag) && + //mmd->hasDocumentation() + mmd->isLinkable() /*mmd->detailsAreVisible()*/ /* && (args==0 || matchArgumentsOld(mmd->argsString(),args)) */ ) @@ -1990,7 +1131,7 @@ bool getDefs(const QCString &scName,const QCString &memberName, { ClassDef *mcd=mmd->memberClass(); int m=minClassDistance(fcd,mcd); - if (m<mdist && mcd->isVisible()) + if (m<mdist && mcd->isLinkable()) { mdist=m; cd=mcd; @@ -2011,18 +1152,19 @@ bool getDefs(const QCString &scName,const QCString &memberName, mmd=mn->last(); while (mmd) { - if ((mmd->protection()!=Private || Config::extractPrivateFlag) && - ( - mmd->hasDocumentation() - /*mmd->detailsAreVisible()*/ - || mmd->isReference() - ) + if (//(mmd->protection()!=Private || Config::extractPrivateFlag) && + //( + //mmd->hasDocumentation() + /*mmd->detailsAreVisible()*/ + //|| mmd->isReference() + //) + mmd->isLinkable() ) { ClassDef *mcd=mmd->memberClass(); //printf(" >Class %s found\n",mcd->name().data()); int m=minClassDistance(fcd,mcd); - if (m<mdist && mcd->isVisible()) + if (m<mdist && mcd->isLinkable()) { //printf("Class distance %d\n",m); mdist=m; @@ -2072,7 +1214,7 @@ bool getDefs(const QCString &scName,const QCString &memberName, } if (namespaceName.length()>0 && (fnd=namespaceDict[namespaceName]) && - fnd->isVisibleExt() + fnd->isLinkable() ) { //printf("Function inside existing namespace `%s'\n",namespaceName.data()); @@ -2083,7 +1225,8 @@ bool getDefs(const QCString &scName,const QCString &memberName, //printf("mmd->getNamespace()=%p fnd=%p\n", // mmd->getNamespace(),fnd); if (mmd->getNamespace()==fnd && - (mmd->isReference() || mmd->hasDocumentation()) + //(mmd->isReference() || mmd->hasDocumentation()) + mmd->isLinkable() ) { // namespace is found bool match=TRUE; @@ -2116,7 +1259,8 @@ bool getDefs(const QCString &scName,const QCString &memberName, while (mmd && !found) { if (mmd->getNamespace()==fnd && - (mmd->isReference() || mmd->hasDocumentation()) + //(mmd->isReference() || mmd->hasDocumentation()) + mmd->isLinkable() ) { nd=fnd; @@ -2134,11 +1278,11 @@ bool getDefs(const QCString &scName,const QCString &memberName, md=mn->first(); while (md) { - if (md->isReference() || md->hasDocumentation()) + if (md->isLinkable()) { //printf("md->name()=`%s'\n",md->name().data()); fd=md->getFileDef(); - if (fd && (fd->isReference() || fd->hasDocumentation())) + if (fd && fd->isLinkable()) { //printf("fd->name()=`%s'\n",fd->name().data()); bool match=TRUE; @@ -2162,11 +1306,11 @@ bool getDefs(const QCString &scName,const QCString &memberName, md=mn->last(); while (md) { - if (md->isReference() || md->hasDocumentation()) + if (md->isLinkable()) { //printf("md->name()=`%s'\n",md->name().data()); fd=md->getFileDef(); - if (fd && (fd->isReference() || fd->hasDocumentation())) + if (fd && fd->isLinkable()) { return TRUE; } @@ -2224,11 +1368,11 @@ bool getScopeDefs(const char *docScope,const char *scope, QCString fullName=scopeName.copy(); if (scopeOffset>0) fullName.prepend(docScopeName.left(scopeOffset)+"::"); - if ((cd=getClass(fullName)) && cd->isVisibleExt()) + if ((cd=getClass(fullName)) && cd->isLinkable()) { return TRUE; // class link written => quit } - else if ((nd=namespaceDict[fullName]) && nd->isVisibleExt()) + else if ((nd=namespaceDict[fullName]) && nd->isLinkable()) { return TRUE; // namespace link written => quit } @@ -2344,7 +1488,7 @@ void generateRef(OutputList &ol,const char *scName, if (getDefs(scopeStr,nameStr,argsStr,md,cd,fd,nd)) { //printf("after getDefs nd=%p\n",nd); - QCString anchor = (md->isReference() || md->hasDocumentation()) ? md->anchor() : 0; + QCString anchor = md->isLinkable() ? md->anchor() : 0; QCString cName,aName; if (cd) // nameStr is a member of cd { @@ -2391,7 +1535,7 @@ void generateRef(OutputList &ol,const char *scName, if (cName.length()>0 || aName.length()>0) { if ( - (cd && !cd->isReference() && cd->isVisible()) || + (cd && cd->isLinkableInProject()) || (fd && !fd->isReference()) || (nd /* TODO: && !nd->isReference() */) ) @@ -2435,7 +1579,7 @@ void generateLink(OutputList &ol,const char *clName, else if ((exampleDict[linkRef])) // link to an example ol.writeObjectLink(0,linkRef+"-example",0,lt); else if ((fd=findFileDef(&inputNameDict,linkRef,ambig)) - && fd->hasDocumentation()) + && fd->isLinkable()) // link to documented input file ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,lt); else // probably a class or member reference @@ -2449,7 +1593,7 @@ void generateFileRef(OutputList &ol,const char *name,const char *text) FileDef *fd; bool ambig; if ((fd=findFileDef(&inputNameDict,name,ambig)) && - fd->hasDocumentation()) + fd->isLinkable()) // link to documented input file ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,linkText); else @@ -34,17 +34,17 @@ class FileNameDict; class ArgumentList; class OutputList; -extern void writeMemberDecs(OutputList &ol, ClassDef *cd, NamespaceDef *nd, - FileDef *fd, const char *title, const char *subtitle, - MemberList *ml); -extern void writeMemberDocs(OutputList &ol, - MemberList *ml,const char *scopeName,MemberDef::MemberType m); +//extern void writeMemberDecs(OutputList &ol, ClassDef *cd, NamespaceDef *nd, +// FileDef *fd, const char *title, const char *subtitle, +// MemberList *ml); +//extern void writeMemberDocs(OutputList &ol, +// MemberList *ml,const char *scopeName,MemberDef::MemberType m); extern void setAnchors(char id,MemberList *ml); //extern int countMemberDocs(MemberList *ml,MemberDef::MemberType m); extern QCString fileToString(const char *name); extern QCString dateToString(bool); -//extern OutputList linkifyText(const char *clName,const char *name, -// const char *text); +extern void linkifyText(OutputList &ol,const char *clName,const char *name, + const char *text); extern bool getDefs(const QCString &scopeName,const QCString &memberName, const char *, MemberDef *&md, ClassDef *&cd,FileDef *&fd, NamespaceDef *&nd); @@ -79,9 +79,18 @@ void startFile(OutputList &ol,const char *name, void endFile(OutputList &ol,bool external=FALSE); void writeQuickLinks(OutputList &ol,bool compact,bool external=FALSE); QCString argListToString(ArgumentList *al); +QCString tempArgListToString(ArgumentList *al); QCString generateMarker(int id); void writeExample(OutputList &ol,ExampleList *el); void setFileNameForSections(QList<QCString> *anchorList,const char *fileName); QCString stripAnnonymousScope(const QCString &s); + +//void writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd, +// FileDef *fd,MemberDef *md,const char *name); +//void warnForUndocumentedMember(MemberDef *md); +QCString stripFromPath(const QCString &path); +bool rightScopeMatch(const QCString &scope, const QCString &name); +bool leftScopeMatch(const QCString &scope, const QCString &name); + #endif |