diff options
author | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2010-11-06 19:00:58 (GMT) |
---|---|---|
committer | dimitri <dimitri@afe2bf4a-e733-0410-8a33-86f594647bc7> | 2010-11-06 19:00:58 (GMT) |
commit | 01f41c40b8505c8f197ef1e5bf7e3a3bc777dc0e (patch) | |
tree | 0a8fa55f942d3a0e2f845bc77e6a357b9fb1c1c7 | |
parent | a32c2461bfbe6705159abfcae92fb11f1309b37c (diff) | |
download | Doxygen-01f41c40b8505c8f197ef1e5bf7e3a3bc777dc0e.zip Doxygen-01f41c40b8505c8f197ef1e5bf7e3a3bc777dc0e.tar.gz Doxygen-01f41c40b8505c8f197ef1e5bf7e3a3bc777dc0e.tar.bz2 |
Release-1.7.2-20101106
-rw-r--r-- | Doxyfile | 6 | ||||
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | README | 4 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | doc/Doxyfile | 2 | ||||
-rw-r--r-- | doc/arch.doc | 7 | ||||
-rw-r--r-- | doc/config.doc | 2 | ||||
-rw-r--r-- | doc/doxygen.sty | 4 | ||||
-rw-r--r-- | src/classdef.cpp | 58 | ||||
-rw-r--r-- | src/config.xml | 20 | ||||
-rw-r--r-- | src/configoptions.cpp | 19 | ||||
-rw-r--r-- | src/docparser.cpp | 5 | ||||
-rw-r--r-- | src/doctokenizer.l | 1 | ||||
-rw-r--r-- | src/dot.cpp | 590 | ||||
-rw-r--r-- | src/dot.h | 18 | ||||
-rw-r--r-- | src/doxygen.cpp | 10 | ||||
-rw-r--r-- | src/doxygen.css | 40 | ||||
-rw-r--r-- | src/doxygen_css.h | 40 | ||||
-rw-r--r-- | src/entry.cpp | 4 | ||||
-rw-r--r-- | src/entry.h | 2 | ||||
-rw-r--r-- | src/fortrancode.l | 8 | ||||
-rw-r--r-- | src/fortranscanner.l | 25 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 13 | ||||
-rw-r--r-- | src/htmlgen.cpp | 4 | ||||
-rw-r--r-- | src/index.cpp | 10 | ||||
-rw-r--r-- | src/index.h | 2 | ||||
-rw-r--r-- | src/instdox.cpp | 3 | ||||
-rw-r--r-- | src/layout.cpp | 5 | ||||
-rw-r--r-- | src/memberlist.cpp | 2 | ||||
-rw-r--r-- | src/scanner.l | 32 | ||||
-rw-r--r-- | src/translator_nl.h | 15 | ||||
-rw-r--r-- | src/util.cpp | 4 | ||||
-rw-r--r-- | src/vhdlscanner.h | 15 | ||||
-rw-r--r-- | src/vhdlscanner.l | 9 |
34 files changed, 715 insertions, 270 deletions
@@ -272,7 +272,7 @@ CLASS_DIAGRAMS = NO MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES -DOT_FONTNAME = FreeSans +DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES @@ -286,7 +286,7 @@ CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png +DOT_IMAGE_FORMAT = svg DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 @@ -294,4 +294,4 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -DOT_CLEANUP = YES +DOT_CLEANUP = NO @@ -1,7 +1,7 @@ -DOXYGEN Version 1.7.2 +DOXYGEN Version 1.7.2-20101106 Please read the installation section of the manual (http://www.doxygen.org/install.html) for instructions. -------- -Dimitri van Heesch (08 October 2010) +Dimitri van Heesch (06 November 2010) @@ -1,4 +1,4 @@ -DOXYGEN Version 1.7.2 +DOXYGEN Version 1.7.2_20101106 Please read INSTALL for compilation instructions. @@ -26,4 +26,4 @@ forum. Enjoy, -Dimitri van Heesch (dimitri@stack.nl) (08 October 2010) +Dimitri van Heesch (dimitri@stack.nl) (06 November 2010) @@ -20,7 +20,7 @@ doxygen_version_minor=7 doxygen_version_revision=2 #NOTE: Setting version_mmn to "NO" will omit mmn info from the package. -doxygen_version_mmn=NO +doxygen_version_mmn=20101106 bin_dirs=`echo $PATH | sed -e "s/:/ /g"` diff --git a/doc/Doxyfile b/doc/Doxyfile index 0c06390..b0f281e 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -44,7 +44,7 @@ EXAMPLE_PATH = ../examples RECURSIVE = NO TAGFILES = ALLEXTERNALS = NO -PERL_PATH = /usr/local/bin/perl +PERL_PATH = /usr/bin/perl SEARCHENGINE = NO PDF_HYPERLINKS = YES USE_PDFLATEX = YES diff --git a/doc/arch.doc b/doc/arch.doc index d257169..939a832 100644 --- a/doc/arch.doc +++ b/doc/arch.doc @@ -199,7 +199,7 @@ wrote the following perl script, which automatically adds or removes -d from the correct line in the Makefile: \verbatim -#!/usr/local/bin/perl +#!/usr/bin/perl $file = shift @ARGV; print "Toggle debugging mode for $file\n"; @@ -216,10 +216,10 @@ if (open(F,"<Makefile.libdoxygen.old")) { } print "Processing Makefile.libdoxygen...\n"; while (<F>) { - if ( s/\(LEX\) -P([a-zA-Z]+)YY -t $file/(LEX) -d -P\1YY -t $file/g ) { + if ( s/\(LEX\) (-i )?-P([a-zA-Z]+)YY -t $file/(LEX) -d \1-P\2YY -t $file/g ) { print "Enabling debug info for $file\n"; } - elsif ( s/\(LEX\) -d -P([a-zA-Z]+)YY -t $file/(LEX) -P\1YY -t $file/g ) { + elsif ( s/\(LEX\) -d (-i )?-P([a-zA-Z]+)YY -t $file/(LEX) \1-P\2YY -t $file/g ) { print "Disabling debug info for $file\n"; } print G "$_"; @@ -234,6 +234,7 @@ else { # touch the file $now = time; utime $now, $now, $file + \endverbatim */ diff --git a/doc/config.doc b/doc/config.doc index e2b098e..1a0e130 100644 --- a/doc/config.doc +++ b/doc/config.doc @@ -2389,7 +2389,7 @@ INPUT = examples/examples.doc src FILE_PATTERNS = *.cc *.h INCLUDE_PATH = examples TAGFILES = qt.tag -PERL_PATH = /usr/local/bin/perl +PERL_PATH = /usr/bin/perl SEARCHENGINE = YES \endverbatim diff --git a/doc/doxygen.sty b/doc/doxygen.sty index 2ee9f91..3c4ba08 100644 --- a/doc/doxygen.sty +++ b/doc/doxygen.sty @@ -25,8 +25,8 @@ {\fancyplain{}{\bfseries\rightmark}} \rhead[\fancyplain{}{\bfseries\leftmark}] {\fancyplain{}{\bfseries\thepage}} -\rfoot[\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2006}]{} -\lfoot[]{\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2006}} +\rfoot[\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2010}]{} +\lfoot[]{\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-2010}} \cfoot{} %---------- Internal commands used in this style file ---------------- diff --git a/src/classdef.cpp b/src/classdef.cpp index 557604f..e38a251 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -169,7 +169,11 @@ class ClassDefImpl */ bool subGrouping; + /** Reason of existance is a "use" relation */ bool usedOnly; + + /** List of titles to use for the summary */ + SDict<QCString> vhdlSummaryTitles; }; void ClassDefImpl::init(const char *defFileName, const char *name, @@ -224,8 +228,9 @@ void ClassDefImpl::init(const char *defFileName, const char *name, } } -ClassDefImpl::ClassDefImpl() +ClassDefImpl::ClassDefImpl() : vhdlSummaryTitles(17) { + vhdlSummaryTitles.setAutoDelete(TRUE); } ClassDefImpl::~ClassDefImpl() @@ -364,6 +369,16 @@ void ClassDef::internalInsertMember(MemberDef *md, //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden()); if (md->isHidden()) return; + static bool optVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + if (optVhdl) + { + QCString title=VhdlDocGen::trVhdlType(md->getMemberSpecifiers(),FALSE); + if (!m_impl->vhdlSummaryTitles.find(title)) + { + m_impl->vhdlSummaryTitles.append(title,new QCString(title)); + } + } + if (!isReference()) { static bool extractPrivate = Config_getBool("EXTRACT_PRIVATE"); @@ -1369,32 +1384,45 @@ void ClassDef::writeAuthorSection(OutputList &ol) void ClassDef::writeSummaryLinks(OutputList &ol) { + static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); QListIterator<LayoutDocEntry> eli( LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); LayoutDocEntry *lde; bool first=TRUE; - for (eli.toFirst();(lde=eli.current());++eli) + + if (!vhdlOpt) { - if (lde->kind()==LayoutDocEntry::ClassNestedClasses && - m_impl->innerClasses && - m_impl->innerClasses->declVisible() - ) + for (eli.toFirst();(lde=eli.current());++eli) { - LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeSummaryLink(ol,"nested-classes",ls->title,first); - } - else if (lde->kind()== LayoutDocEntry::MemberDecl) - { - LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; - MemberList * ml = getMemberList(lmd->type); - if (ml && ml->declVisible()) + if (lde->kind()==LayoutDocEntry::ClassNestedClasses && + m_impl->innerClasses && + m_impl->innerClasses->declVisible() + ) { - writeSummaryLink(ol,ml->listTypeAsString(),lmd->title,first); + LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; + writeSummaryLink(ol,"nested-classes",ls->title,first); + } + else if (lde->kind()== LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + MemberList * ml = getMemberList(lmd->type); + if (ml && ml->declVisible()) + { + writeSummaryLink(ol,ml->listTypeAsString(),lmd->title,first); + } } } } + else // VDHL only + { + SDict<QCString>::Iterator li(m_impl->vhdlSummaryTitles); + for (li.toFirst();li.current();++li) + { + writeSummaryLink(ol,li.current()->data(),li.current()->data(),first); + } + } if (!first) { ol.writeString(" </div>\n"); diff --git a/src/config.xml b/src/config.xml index 6441508..be324a4 100644 --- a/src/config.xml +++ b/src/config.xml @@ -1267,15 +1267,15 @@ instead of the = operator. If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this tag can be used to specify a list of macro names that should be expanded. The macro definition that is found in the sources will be used. -Use the PREDEFINED tag if you want to use a different macro definition. +Use the PREDEFINED tag if you want to use a different macro definition that +overrules the definition found in the source code. ' depends='ENABLE_PREPROCESSING'> </option> <option type='bool' id='SKIP_FUNCTION_MACROS' docs=' If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -doxygen's preprocessor will remove all function-like macros that are alone -on a line, have an all uppercase name, and do not end with a semicolon. Such -function macros are typically used for boiler-plate code, and will confuse -the parser if not removed. +doxygen's preprocessor will remove all references to function-like macros +that are alone on a line, have an all uppercase name, and do not end with a +semicolon, because these will confuse the parser if not removed. ' defval='1' depends='ENABLE_PREPROCESSING'/> </group> <group name='External' docs='Configuration::additions related to external references'> @@ -1350,15 +1350,14 @@ explicitly to a value larger than 0 to get control over the balance between CPU load and processing speed. ' defval='0' minval='0' maxval='32'/> <option type='string' id='DOT_FONTNAME' format='string' docs=' -By default doxygen will write a font called FreeSans.ttf to the output -directory and reference it in all dot files that doxygen generates. This -font does not include all possible unicode characters however, so when you need -these (or just want a differently looking font) you can specify the font name +By default doxygen will write a font called Helvetica to the output +directory and reference it in all dot files that doxygen generates. +When you want a differently looking font you can specify the font name using DOT_FONTNAME. You need need to make sure dot is able to find the font, which can be done by putting it in a standard location or by setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory containing the font. -' defval='FreeSans.ttf' depends='HAVE_DOT'/> +' defval='Helvetica' depends='HAVE_DOT'/> <option type='int' id='DOT_FONTSIZE' docs=' The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. The default size is 10pt. @@ -1438,6 +1437,7 @@ If left blank png will be used. <value name='png'/> <value name='jpg'/> <value name='gif'/> + <value name='svg'/> </option> <option type='string' id='DOT_PATH' format='dir' docs=' The tag DOT_PATH can be used to specify the path where the dot tool can be diff --git a/src/configoptions.cpp b/src/configoptions.cpp index 0dbee23..38f7ed8 100644 --- a/src/configoptions.cpp +++ b/src/configoptions.cpp @@ -1922,17 +1922,16 @@ void addConfigOptions(Config *cfg) "If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then\n" "this tag can be used to specify a list of macro names that should be expanded.\n" "The macro definition that is found in the sources will be used.\n" - "Use the PREDEFINED tag if you want to use a different macro definition." + "Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code." ); cl->addDependency("ENABLE_PREPROCESSING"); //---- cb = cfg->addBool( "SKIP_FUNCTION_MACROS", "If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then\n" - "doxygen's preprocessor will remove all function-like macros that are alone\n" - "on a line, have an all uppercase name, and do not end with a semicolon. Such\n" - "function macros are typically used for boiler-plate code, and will confuse\n" - "the parser if not removed.", + "doxygen's preprocessor will remove all references to function-like macros\n" + "that are alone on a line, have an all uppercase name, and do not end with a\n" + "semicolon, because these will confuse the parser if not removed.", TRUE ); cb->addDependency("ENABLE_PREPROCESSING"); @@ -2046,16 +2045,15 @@ void addConfigOptions(Config *cfg) //---- cs = cfg->addString( "DOT_FONTNAME", - "By default doxygen will write a font called FreeSans.ttf to the output\n" - "directory and reference it in all dot files that doxygen generates. This\n" - "font does not include all possible unicode characters however, so when you need\n" - "these (or just want a differently looking font) you can specify the font name\n" + "By default doxygen will write a font called Helvetica to the output\n" + "directory and reference it in all dot files that doxygen generates.\n" + "When you want a differently looking font you can specify the font name\n" "using DOT_FONTNAME. You need need to make sure dot is able to find the font,\n" "which can be done by putting it in a standard location or by setting the\n" "DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory\n" "containing the font." ); - cs->setDefaultValue("FreeSans.ttf"); + cs->setDefaultValue("Helvetica"); cs->addDependency("HAVE_DOT"); //---- ci = cfg->addInt( @@ -2190,6 +2188,7 @@ void addConfigOptions(Config *cfg) ce->addValue("png"); ce->addValue("jpg"); ce->addValue("gif"); + ce->addValue("svg"); ce->addDependency("HAVE_DOT"); //---- cs = cfg->addString( diff --git a/src/docparser.cpp b/src/docparser.cpp index 1b95a8c..1b51d0a 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -1008,7 +1008,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children) ClassDef *cd=0; bool ambig; FileDef *fd = findFileDef(Doxygen::inputNameDict,g_fileName,ambig); - //printf("handleLinkedWord(%s) g_context=%s\n",name.data(),g_context.data()); + //printf("handleLinkedWord(%s) g_context=%s\n",g_token->name.data(),g_context.data()); if (!g_insideHtmlLink && (resolveRef(g_context,g_token->name,g_inSeeBlock,&compound,&member,TRUE,fd,TRUE) || (!g_context.isEmpty() && // also try with global scope @@ -1104,7 +1104,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children) } else // normal non-linkable word { - if (g_token->name.left(1)=='#' || g_token->name.left(2)=="::") + if (g_token->name.left(1)=="#" || g_token->name.left(2)=="::") { warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: explicit link request to '%s' could not be resolved",qPrint(name)); } @@ -5662,6 +5662,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case XML_PARAM: case XML_TYPEPARAM: case XML_RETURNS: + case XML_SEE: case XML_SEEALSO: case XML_EXCEPTION: retval = RetVal_CloseXml; diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 0f7dcc1..5cec5d7 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -259,6 +259,7 @@ static void handleHtmlTag() static QCString stripEmptyLines(const char *s) { + if (s==0) return QCString(); int result=0,p=0; for (;;) { diff --git a/src/dot.cpp b/src/dot.cpp index 94c915c..523d515 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -48,7 +48,7 @@ #define MAP_CMD "cmapx" -//#define FONTNAME "FreeSans" +//#define FONTNAME "Helvetica" #define FONTNAME getDotFontName() #define FONTSIZE getDotFontSize() @@ -86,7 +86,11 @@ static const char *edgeStyleMap[] = static QCString getDotFontName() { static QCString dotFontName = Config_getString("DOT_FONTNAME"); - if (dotFontName.isEmpty()) dotFontName="FreeSans.ttf"; + if (dotFontName.isEmpty()) + { + //dotFontName="FreeSans.ttf"; + dotFontName="Helvetica"; + } return dotFontName; } @@ -118,6 +122,79 @@ static void writeGraphFooter(FTextStream &t) t << "}" << endl; } +static QCString replaceRef(const QCString &buf,const QCString relPath, + bool urlOnly,const QCString &context,const QCString &target=QCString()) +{ + // search for href="...", store ... part in link + QCString href = "href"; + bool isXLink=FALSE; + int len = 6; + int indexS = buf.find("href=\""), indexE; + if (indexS>5 && buf.find("xlink:href=\"")!=-1) // XLink href (for SVG) + { + indexS-=6; + len+=6; + href.prepend("xlink:"); + isXLink=TRUE; + } + if (indexS>=0 && (indexE=buf.find('"',indexS+len))!=-1) + { + QCString link = buf.mid(indexS+len,indexE-indexS-len); + QCString result; + if (urlOnly) // for user defined dot graphs + { + if (link.left(5)=="\\ref " || link.left(5)=="@ref ") // \ref url + { + result=href+"=\""; + // fake ref node to resolve the url + DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context ); + result+=externalRef(relPath,df->ref(),TRUE); + if (!df->file().isEmpty()) + result += df->file().data() + Doxygen::htmlFileExtension; + if (!df->anchor().isEmpty()) + result += "#" + df->anchor(); + delete df; + result += "\""; + } + else + { + result = href+"=\"" + link + "\""; + } + } + else // ref$url (external ref via tag file), or $url (local ref) + { + int marker = link.find('$'); + if (marker!=-1) + { + QCString ref = link.left(marker); + QCString url = link.mid(marker+1); + if (!ref.isEmpty()) + { + result = externalLinkTarget() + externalRef(relPath,ref,FALSE); + } + result+= href+"=\""; + result+=externalRef(relPath,ref,TRUE); + result+= url + "\""; + } + else // should not happen, but handle properly anyway + { + result = href+"=\"" + link + "\""; + } + } + if (!target.isEmpty()) + { + result+=" target=\""+target+"\""; + } + QCString leftPart = buf.left(indexS); + QCString rightPart = buf.mid(indexE+1); + return leftPart + result + rightPart; + } + else + { + return buf; + } +} + /*! converts the rectangles in a client site image map into a stream * \param t the stream to which the result is written. * \param mapName the name of the map file. @@ -150,57 +227,7 @@ static bool convertMapFile(FTextStream &t,const char *mapName, if (buf.left(5)=="<area") { - // search for href="...", store ... part in link - int indexS = buf.find("href=\""), indexE; - if (indexS!=-1 && (indexE=buf.find('"',indexS+6))!=-1) - { - QCString link = buf.mid(indexS+6,indexE-indexS-6); - QCString result; - if (urlOnly) // for user defined dot graphs - { - if (link.left(5)=="\\ref " || link.left(5)=="@ref ") // \ref url - { - result="href=\""; - // fake ref node to resolve the url - DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context ); - result+=externalRef(relPath,df->ref(),TRUE); - if (!df->file().isEmpty()) - result += df->file().data() + Doxygen::htmlFileExtension; - if (!df->anchor().isEmpty()) - result += "#" + df->anchor(); - delete df; - result += "\""; - } - else - { - result = "href=\"" + link + "\""; - } - } - else // ref$url (external ref via tag file), or $url (local ref) - { - int marker = link.find('$'); - if (marker!=-1) - { - QCString ref = link.left(marker); - QCString url = link.mid(marker+1); - if (!ref.isEmpty()) - { - result = externalLinkTarget() + externalRef(relPath,ref,FALSE); - } - result+= "href=\""; - result+=externalRef(relPath,ref,TRUE); - result+= url + "\""; - } - else // should not happen, but handle properly anyway - { - result = "href=\"" + link + "\""; - } - } - QCString leftPart = buf.left(indexS); - QCString rightPart = buf.mid(indexE+1); - buf = leftPart + result + rightPart; - } - t << buf; + t << replaceRef(buf,relPath,urlOnly,context); } } return TRUE; @@ -376,6 +403,64 @@ static bool writeVecGfxFigure(FTextStream &out,const QCString &baseName, return TRUE; } +// extract size from a dot generated SVG file +static bool readSVGSize(const QCString &fileName,int *width,int *height) +{ + bool found=FALSE; + QFile f(fileName); + if (!f.open(IO_ReadOnly)) + { + return FALSE; + } + const int maxLineLen=4096; + char buf[maxLineLen]; + while (!f.atEnd() && !found) + { + int numBytes = f.readLine(buf,maxLineLen-1); // read line + if (numBytes>0) + { + buf[numBytes]='\0'; + if (sscanf(buf,"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2) + { + found=TRUE; + } + } + else // read error! + { + //printf("Read error %d!\n",numBytes); + return FALSE; + } + } + return TRUE; +} + +static void writeSVGNotSupported(FTextStream &out) +{ + out << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; +} + +// check if a reference to a SVG figure can be written and does so if possible. +// return FALSE if not possible (for instance because the SVG file is not yet generated). +static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName) +{ + int width=600,height=450; + if (!readSVGSize(absImgName,&width,&height)) + { + return FALSE; + } +// out << "<object type=\"image/svg+xml\" data=\"" + out << "<iframe src=\"" + << relPath << baseName << ".svg\" width=\"" + << ((width*96+48)/72) << "\" height=\"" + << ((height*96+48)/72) << "\">"; + writeSVGNotSupported(out); +// out << "</object>"; + out << "</iframe>"; + + return TRUE; +} + // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. static void checkDotResult(const QCString &imgName) @@ -588,13 +673,13 @@ error: //-------------------------------------------------------------------- -DotMapConverter::DotMapConverter(const char *patchFile) +DotFilePatcher::DotFilePatcher(const char *patchFile) : m_patchFile(patchFile) { m_maps.setAutoDelete(TRUE); } -int DotMapConverter::addMap(const QCString &mapFile,const QCString &relPath, +int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, bool urlOnly,const QCString &context,const QCString &label) { int id = m_maps.count(); @@ -608,8 +693,8 @@ int DotMapConverter::addMap(const QCString &mapFile,const QCString &relPath, return id; } -int DotMapConverter::addFigure(const QCString &baseName, - const QCString &figureName,bool heightCheck) +int DotFilePatcher::addFigure(const QCString &baseName, + const QCString &figureName,bool heightCheck) { int id = m_maps.count(); Map *map = new Map; @@ -620,9 +705,35 @@ int DotMapConverter::addFigure(const QCString &baseName, return id; } -bool DotMapConverter::run() +int DotFilePatcher::addSVGConversion(const QCString &relPath,bool urlOnly, + const QCString &context) { - //printf("DotMapConverter::run(): %s\n",m_patchFile.data()); + int id = m_maps.count(); + Map *map = new Map; + map->relPath = relPath; + map->urlOnly = urlOnly; + map->context = context; + m_maps.append(map); + return id; +} + +int DotFilePatcher::addSVGObject(const QCString &baseName, + const QCString &absImgName, + const QCString &relPath) +{ + int id = m_maps.count(); + Map *map = new Map; + map->mapFile = absImgName; + map->relPath = relPath; + map->label = baseName; + m_maps.append(map); + return id; +} + +bool DotFilePatcher::run() +{ + //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); + bool isSVGFile = m_patchFile.right(4)==".svg"; QCString tmpName = m_patchFile+".tmp"; if (!QDir::current().rename(m_patchFile,tmpName)) { @@ -649,12 +760,41 @@ bool DotMapConverter::run() { QCString line(maxLineLen); int numBytes = fi.readLine(line.data(),maxLineLen); + //printf("line=[%s]\n",line.stripWhiteSpace().data()); int i; ASSERT(numBytes<maxLineLen); - if ((i=line.find("<!-- MAP"))!=-1) + if (isSVGFile) + { + Map *map = m_maps.at(0); // there is only one 'map' for a SVG file + t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); + } + else if ((i=line.find("<!-- SVG"))!=-1 || (i=line.find("[!-- SVG"))!=-1) + { + //printf("Found marker at %d\n",i); + int mapId=-1; + t << line.left(i); + int n = sscanf(line.data()+i+1,"!-- SVG %d",&mapId); + if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) + { + int e = QMAX(line.find("--]"),line.find("-->")); + Map *map = m_maps.at(mapId); + if (!writeSVGFigureLink(t,map->relPath,map->label,map->mapFile)) + { + err("Problem extracting size from SVG file %s\n",map->mapFile.data()); + } + if (e!=-1) t << line.mid(e+3); + } + else // error invalid map id! + { + err("Found invalid SVG id in file %s!\n",m_patchFile.data()); + t << line.mid(i); + } + } + else if ((i=line.find("<!-- MAP"))!=-1) { int mapId=-1; - int n = sscanf(line,"<!-- MAP %d",&mapId); + t << line.left(i); + int n = sscanf(line.data()+i,"<!-- MAP %d",&mapId); if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) { Map *map = m_maps.at(mapId); @@ -666,8 +806,8 @@ bool DotMapConverter::run() } else // error invalid map id! { - err("Found invalid MAP id in file %s!\n",mapId,m_patchFile.data()); - t << line; + err("Found invalid MAP id in file %s!\n",m_patchFile.data()); + t << line.mid(i); } } else if ((i=line.find("% FIG"))!=-1) @@ -808,10 +948,10 @@ int DotManager::addMap(const QCString &file,const QCString &mapFile, const QCString &relPath,bool urlOnly,const QCString &context, const QCString &label) { - DotMapConverter *map = m_dotMaps.find(file); + DotFilePatcher *map = m_dotMaps.find(file); if (map==0) { - map = new DotMapConverter(file); + map = new DotFilePatcher(file); m_dotMaps.append(file,map); } return map->addMap(mapFile,relPath,urlOnly,context,label); @@ -820,15 +960,39 @@ int DotManager::addMap(const QCString &file,const QCString &mapFile, int DotManager::addFigure(const QCString &file,const QCString &baseName, const QCString &figureName,bool heightCheck) { - DotMapConverter *map = m_dotMaps.find(file); + DotFilePatcher *map = m_dotMaps.find(file); if (map==0) { - map = new DotMapConverter(file); + map = new DotFilePatcher(file); m_dotMaps.append(file,map); } return map->addFigure(baseName,figureName,heightCheck); } +int DotManager::addSVGConversion(const QCString &file,const QCString &relPath, + bool urlOnly,const QCString &context) +{ + DotFilePatcher *map = m_dotMaps.find(file); + if (map==0) + { + map = new DotFilePatcher(file); + m_dotMaps.append(file,map); + } + return map->addSVGConversion(relPath,urlOnly,context); +} + +int DotManager::addSVGObject(const QCString &file,const QCString &baseName, + const QCString &absImgName,const QCString &relPath) +{ + DotFilePatcher *map = m_dotMaps.find(file); + if (map==0) + { + map = new DotFilePatcher(file); + m_dotMaps.append(file,map); + } + return map->addSVGObject(baseName,absImgName,relPath); +} + bool DotManager::run() { uint numDotRuns = m_dotRuns.count(); @@ -903,11 +1067,11 @@ bool DotManager::run() // patch the output file and insert the maps and figures i=1; - SDict<DotMapConverter>::Iterator di(m_dotMaps); - DotMapConverter *map; + SDict<DotFilePatcher>::Iterator di(m_dotMaps); + DotFilePatcher *map; for (di.toFirst();(map=di.current());++di) { - msg("Inserting map/figure %d/%d\n",i,numDotMaps); + msg("Patching output file %d/%d\n",i,numDotMaps); if (!map->run()) return FALSE; i++; } @@ -1640,14 +1804,32 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, Doxygen::indexList.addImageFile(imgName); // write image and map in a table row QCString mapLabel = escapeCharsInString(n->m_label,FALSE); - out << "<tr><td><img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#" + out << "<tr><td>"; + if (imgExt=="svg") // vector graphics + { + if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName)) + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,QCString(), + FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName, + absImgName,QCString()); + out << "<!-- SVG " << mapId << " -->" << endl; + } + } + else // normal bitmap + { + out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#" << mapLabel << "\"/>" << endl; - if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(), - FALSE,QCString(),mapLabel); - out << "<!-- MAP " << mapId << " -->" << endl; + if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(), + FALSE,QCString(),mapLabel); + out << "<!-- MAP " << mapId << " -->" << endl; + } } out << "</td></tr>" << endl; @@ -2362,6 +2544,7 @@ QCString DotClassGraph::writeGraph(FTextStream &out, } baseName = convertNameToFile(diskName()); + // derive target file names from baseName QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); QCString absBaseName = QCString(d.absPath())+"/"+baseName; QCString absDotName = absBaseName+".dot"; @@ -2416,27 +2599,47 @@ QCString DotClassGraph::writeGraph(FTextStream &out, { QCString mapLabel = escapeCharsInString(m_startNode->m_label,FALSE)+"_"+ escapeCharsInString(mapName,FALSE); - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapLabel << "\" alt=\""; - switch (m_graphType) + if (imgExt=="svg") // add link to SVG file without map file { - case DotNode::Collaboration: - out << "Collaboration graph"; - break; - case DotNode::Inheritance: - out << "Inheritance graph"; - break; - default: - ASSERT(0); - break; + out << "<div class=\"center\">"; + if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); + out << "<!-- SVG " << mapId << " -->" << endl; + } + out << "</div>" << endl; } - out << "\"/></div>" << endl; - if (regenerate || !insertMapFile(out,absMapName,relPath,mapLabel)) + else // add link to bitmap file with image map { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapLabel); - out << "<!-- MAP " << mapId << " -->" << endl; + out << "<div class=\"center\">"; + out << "<img src=\"" << relPath << baseName << "." + << imgExt << "\" border=\"0\" usemap=\"#" + << mapLabel << "\" alt=\""; + switch (m_graphType) + { + case DotNode::Collaboration: + out << "Collaboration graph"; + break; + case DotNode::Inheritance: + out << "Inheritance graph"; + break; + default: + ASSERT(0); + break; + } + out << "\"/>"; + out << "</div>" << endl; + + if (regenerate || !insertMapFile(out,absMapName,relPath,mapLabel)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, + FALSE,QCString(),mapLabel); + out << "<!-- MAP " << mapId << " -->" << endl; + } } } else if (format==EPS) // produce tex to include the .eps image @@ -2712,21 +2915,37 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out, if (format==BITMAP && generateImageMap) { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapName << "\" alt=\"\"/>"; - out << "</div>" << endl; - - QCString absMapName = absBaseName+".map"; - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + if (imgExt=="svg") // Scalable vector graphics + { + out << "<div class=\"center\">"; + if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); + out << "<!-- SVG " << mapId << " -->" << endl; + } + out << "</div>" << endl; + } + else // bitmap graphics { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; + out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." + << imgExt << "\" border=\"0\" usemap=\"#" + << mapName << "\" alt=\"\"/>"; + out << "</div>" << endl; + + QCString absMapName = absBaseName+".map"; + if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, + FALSE,QCString(),mapName); + out << "<!-- MAP " << mapId << " -->" << endl; + } } - } - else if (format==EPS) + else if (format==EPS) // encapsulated postscript { if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) { @@ -2986,21 +3205,37 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat format, if (format==BITMAP && generateImageMap) { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapName << "\" alt=\""; - out << "\"/>"; - out << "</div>" << endl; - - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + if (imgExt=="svg") // Scalable vector graphics { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; + out << "<div class=\"center\">"; + if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); + out << "<!-- SVG " << mapId << " -->" << endl; + } + out << "</div>" << endl; } + else // bitmap graphics + { + out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." + << imgExt << "\" border=\"0\" usemap=\"#" + << mapName << "\" alt=\""; + out << "\"/>"; + out << "</div>" << endl; + if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, + FALSE,QCString(),mapName); + out << "<!-- MAP " << mapId << " -->" << endl; + } + } } - else if (format==EPS) + else if (format==EPS) // encapsulated postscript { if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) { @@ -3114,18 +3349,35 @@ QCString DotDirDeps::writeGraph(FTextStream &out, if (format==BITMAP && generateImageMap) { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapName << "\" alt=\""; - out << convertToXML(m_dir->displayName()); - out << "\"/>"; - out << "</div>" << endl; - - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + if (imgExt=="svg") // Scalable vector graphics { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - TRUE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; + out << "<div class=\"center\">"; + if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); + out << "<!-- SVG " << mapId << " -->" << endl; + } + out << "</div>" << endl; + } + else // bitmap graphics + { + out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." + << imgExt << "\" border=\"0\" usemap=\"#" + << mapName << "\" alt=\""; + out << convertToXML(m_dir->displayName()); + out << "\"/>"; + out << "</div>" << endl; + + if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, + TRUE,QCString(),mapName); + out << "<!-- MAP " << mapId << " -->" << endl; + } } } else if (format==EPS) @@ -3214,6 +3466,14 @@ void generateGraphLegend(const char *path) } Doxygen::indexList.addImageFile(imgName); + if (imgExt=="svg") + { + DotManager::instance()->addSVGObject( + absBaseName+Config_getString("HTML_FILE_EXTENSION"), + "graph_legend", + absImgName,QCString()); + } + } void writeDotGraphFromFile(const char *inFile,const char *outDir, @@ -3258,16 +3518,16 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, } -/*! Marco Dalla Gasperina [marcodg@attbi.com] added this to allow - * dotfiles to generate image maps. +/*! Writes user defined image map to the output. + * \param t text stream to write to * \param inFile just the basename part of the filename * \param outDir output directory * \param relPath relative path the to root of the output dir * \param context the scope in which this graph is found (for resolving links) - * \returns a string which is the HTML image map (without the \<map\>\</map\>) */ -QCString getDotImageMapFromFile(const QCString& inFile, const QCString& outDir, - const QCString &relPath, const QCString &context) +void writeDotImageMapFromFile(FTextStream &t, + const QCString& inFile, const QCString& outDir, + const QCString &relPath, const QCString &context) { QCString outFile = inFile + ".map"; @@ -3282,17 +3542,32 @@ QCString getDotImageMapFromFile(const QCString& inFile, const QCString& outDir, dotRun.preventCleanUp(); if (!dotRun.run()) { - return ""; + return; } - QGString result; - FTextStream tmpout(&result); - convertMapFile(tmpout, outFile, relPath ,TRUE, context); - d.remove(outFile); + QCString mapName = inFile+".map"; + QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); - return result.data(); + if (imgExt=="svg") // vector graphics + { + writeSVGFigureLink(t,relPath,inFile,inFile+".svg"); + DotFilePatcher patcher(inFile+".svg"); + patcher.addSVGConversion(relPath,TRUE,context); + patcher.run(); + } + else // bitmap graphics + { + t << "<img src=\"" << relPath << inFile << "." + << imgExt << "\" alt=\"" + << inFile << "\" border=\"0\" usemap=\"#" << mapName << "\">" << endl + << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">"; + + convertMapFile(t, outFile, relPath ,TRUE, context); + + t << "</map>" << endl; + } + d.remove(outFile); } -// end MDG mods //------------------------------------------------------------- @@ -3605,14 +3880,33 @@ QCString DotGroupCollaboration::writeGraph( FTextStream &t, GraphOutputFormat fo if (format==BITMAP && writeImageMap) { QCString mapLabel = escapeCharsInString(baseName,FALSE); - t << "<center><table><tr><td><img src=\"" << relPath << imgName - << "\" border=\"0\" alt=\"\" usemap=\"#" - << mapLabel << "\"/>" << endl; - if (regenerate || !insertMapFile(t,absMapName,relPath,mapLabel)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapLabel); - t << "<!-- MAP " << mapId << " -->" << endl; + t << "<center><table><tr><td>"; + + if (imgExt=="svg") + { + t << "<div class=\"center\">"; + if (regenerate || !writeSVGFigureLink(t,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file + { + if (regenerate) + { + DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString()); + } + int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); + t << "<!-- SVG " << mapId << " -->" << endl; + } + t << "</div>" << endl; + } + else + { + t << "<img src=\"" << relPath << imgName + << "\" border=\"0\" alt=\"\" usemap=\"#" + << mapLabel << "\"/>" << endl; + if (regenerate || !insertMapFile(t,absMapName,relPath,mapLabel)) + { + int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, + FALSE,QCString(),mapLabel); + t << "<!-- MAP " << mapId << " -->" << endl; + } } t << "</td></tr></table></center>" << endl; @@ -357,7 +357,7 @@ class DotRunner }; /** @brief Helper class to insert a set of map file into an output file */ -class DotMapConverter +class DotFilePatcher { public: struct Map @@ -368,11 +368,14 @@ class DotMapConverter QCString context; QCString label; }; - DotMapConverter(const char *patchFile); + DotFilePatcher(const char *patchFile); int addMap(const QCString &mapFile,const QCString &relPath, bool urlOnly,const QCString &context,const QCString &label); int addFigure(const QCString &baseName, const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly,const QCString &context); + int addSVGObject(const QCString &baseName, const QCString &figureName, + const QCString &relPath); bool run(); private: @@ -415,13 +418,17 @@ class DotManager const QCString &context,const QCString &label); int addFigure(const QCString &file,const QCString &baseName, const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &file,const QCString &relPath, + bool urlOnly,const QCString &context); + int addSVGObject(const QCString &file,const QCString &baseName, + const QCString &figureNAme,const QCString &relPath); bool run(); private: DotManager(); virtual ~DotManager(); QList<DotRunner> m_dotRuns; - SDict<DotMapConverter> m_dotMaps; + SDict<DotFilePatcher> m_dotMaps; static DotManager *m_theInstance; DotRunnerQueue *m_queue; QList<DotWorkerThread> m_workers; @@ -433,8 +440,9 @@ void generateGraphLegend(const char *path); void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format); -QCString getDotImageMapFromFile(const QCString& inFile, const QCString& outDir, - const QCString& relPath,const QCString& context); +void writeDotImageMapFromFile(FTextStream &t, + const QCString& inFile, const QCString& outDir, + const QCString& relPath,const QCString& context); void writeDotDirDepGraph(FTextStream &t,DirDef *dd); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 3efe75d..7ff5c89 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -2197,8 +2197,9 @@ static MemberDef *addVariableToFile( * \returns -1 if this is not a function pointer variable or * the index at which the brace of (...*name) was found. */ -static int findFunctionPtr(const QCString &type,int *pLength=0) +static int findFunctionPtr(const QCString &type,int lang, int *pLength=0) { + if (lang == SrcLangExt_F90) return -1; // Fortran does not have function pointers static const QRegExp re("([^)]*[\\*\\^][^)]*)"); int i=-1,l; if (!type.isEmpty() && // return type is non-empty @@ -2381,7 +2382,7 @@ static void addVariable(EntryNav *rootNav,int isFuncPtr=-1) else { int i=isFuncPtr; - if (i==-1) i=findFunctionPtr(root->type); // for typedefs isFuncPtr is not yet set + if (i==-1) i=findFunctionPtr(root->type,root->lang); // for typedefs isFuncPtr is not yet set if (i!=-1) // function pointer { int ai = root->type.find('[',i); @@ -2593,7 +2594,7 @@ static void buildVarList(EntryNav *rootNav) (rootNav->section()==Entry::VARIABLE_SEC // it's a variable ) || (rootNav->section()==Entry::FUNCTION_SEC && // or maybe a function pointer variable - (isFuncPtr=findFunctionPtr(rootNav->type()))!=-1 + (isFuncPtr=findFunctionPtr(rootNav->type(),rootNav->lang()))!=-1 ) || (rootNav->section()==Entry::FUNCTION_SEC && // class variable initialized by constructor isVarWithConstructor(rootNav) @@ -6164,7 +6165,7 @@ static void filterMemberDocumentation(EntryNav *rootNav) } if ( // detect func variable/typedef to func ptr - (i=findFunctionPtr(root->type,&l))!=-1 + (i=findFunctionPtr(root->type,root->lang,&l))!=-1 ) { //printf("Fixing function pointer!\n"); @@ -10393,6 +10394,7 @@ void generateOutput() // what categories we find in this function. if (Config_getBool("GENERATE_HTML") && searchEngine) { + msg("Generating search indices...\n"); QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search"; QDir searchDir(searchDirName); if (!searchDir.exists() && !searchDir.mkdir(searchDirName)) diff --git a/src/doxygen.css b/src/doxygen.css index 39053f8..3a07205 100644 --- a/src/doxygen.css +++ b/src/doxygen.css @@ -683,4 +683,44 @@ div.headertitle { padding: 5px 5px 5px 10px; } +dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug +{ + border-left:4px solid; + padding: 0 0 0 6px; +} + +dl.note +{ + border-color: #D0D000; +} + +dl.warning, dl.attention +{ + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + border-color: #00D000; +} + +dl.deprecated +{ + border-color: #505050; +} + +dl.todo +{ + border-color: #00C0E0; +} + +dl.test +{ + border-color: #3030E0; +} + +dl.bug +{ + border-color: #C08050; +} diff --git a/src/doxygen_css.h b/src/doxygen_css.h index f32c905..63bcd89 100644 --- a/src/doxygen_css.h +++ b/src/doxygen_css.h @@ -683,4 +683,44 @@ "{\n" " padding: 5px 5px 5px 10px;\n" "}\n" +"dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug\n" +"{\n" +" border-left:4px solid;\n" +" padding: 0 0 0 6px;\n" +"}\n" +"\n" +"dl.note\n" +"{\n" +" border-color: #D0D000;\n" +"}\n" +"\n" +"dl.warning, dl.attention\n" +"{\n" +" border-color: #FF0000;\n" +"}\n" +"\n" +"dl.pre, dl.post, dl.invariant\n" +"{\n" +" border-color: #00D000;\n" +"}\n" +"\n" +"dl.deprecated\n" +"{\n" +" border-color: #505050;\n" +"}\n" +"\n" +"dl.todo\n" +"{\n" +" border-color: #00C0E0;\n" +"}\n" +"\n" +"dl.test\n" +"{\n" +" border-color: #3030E0;\n" +"}\n" +"\n" +"dl.bug\n" +"{\n" +" border-color: #C08050;\n" +"}\n" "\n" diff --git a/src/entry.cpp b/src/entry.cpp index c8475a6..2bde394 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -365,8 +365,8 @@ void Entry::addSpecialListItem(const char *listName,int itemId) EntryNav::EntryNav(EntryNav *parent, Entry *e) : m_parent(parent), m_subList(0), m_section(e->section), m_type(e->type), - m_name(e->name), m_fileDef(0), m_info(0), m_offset(-1), - m_noLoad(FALSE) + m_name(e->name), m_fileDef(0), m_lang(e->lang), + m_info(0), m_offset(-1), m_noLoad(FALSE) { if (e->tagInfo) { diff --git a/src/entry.h b/src/entry.h index 9e9aa84..6460fec 100644 --- a/src/entry.h +++ b/src/entry.h @@ -413,6 +413,7 @@ class EntryNav Entry *entry() const { return m_info; } int section() const { return m_section; } + SrcLangExt lang() const { return m_lang; } const QCString &type() const { return m_type; } const QCString &name() const { return m_name; } TagInfo *tagInfo() const { return m_tagInfo; } @@ -432,6 +433,7 @@ class EntryNav QCString m_name; //!< member name TagInfo *m_tagInfo; //!< tag file info FileDef *m_fileDef; + SrcLangExt m_lang; //!< programming language in which this entry was found Entry *m_info; int64 m_offset; diff --git a/src/fortrancode.l b/src/fortrancode.l index d8f592c..2923ad6 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -645,12 +645,16 @@ B [ \t] BS [ \t]* BS_ [ \t]+ COMMA {BS},{BS} -ARGS {BS}("("[^)]*")"){BS} +ARGS_L0 ("("[^)]*")") +ARGS_L1a [^()]*"("[^)]*")"[^)]* +ARGS_L1 ("("{ARGS_L1a}*")") +ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" +ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) NUM_TYPE (complex|integer|logical|real) KIND {ARGS} CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) -TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{B}PRECISION|{CHAR}) +TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS_}PRECISION|{CHAR}|TYPE{ARGS}) INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" ATTR_SPEC (ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PRIVATE|PUBLIC|SAVE|TARGET|RECURSIVE|PURE|ELEMENTAL) diff --git a/src/fortranscanner.l b/src/fortranscanner.l index b8d4afd..cb6a9f9 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -210,7 +210,11 @@ B [ \t] BS [ \t]* BS_ [ \t]+ COMMA {BS},{BS} -ARGS {BS}("("[^)]*")") +ARGS_L0 ("("[^)]*")") +ARGS_L1a [^()]*"("[^)]*")"[^)]* +ARGS_L1 ("("{ARGS_L1a}*")") +ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" +ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) NOARGS {BS}"\n" NUM_TYPE (complex|integer|logical|real) @@ -377,6 +381,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA current->section=Entry::USINGDIR_SEC; current_root->addSubEntry(current); current = new Entry; + current->lang = SrcLangExt_F90; yy_pop_state(); } <Use>{ID}/, { @@ -391,6 +396,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA current->section=Entry::USINGDECL_SEC; current_root->addSubEntry(current); current = new Entry ; + current->lang = SrcLangExt_F90; } <Use,UseOnly>"\n" { unput(*yytext); @@ -398,7 +404,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA } /*------ ignore special fortran statements */ -<Start,ModuleBody,SubprogBody>^[ \t]*interface({BS_}{ID}({BS}\({BS}[^ \t()]+{BS}\))?)?/{BS}(!|\n) { // handle interface block +<Start,ModuleBody,SubprogBody>^[ \t]*interface({BS_}{ID}({ARGS}?)?)?/{BS}(!|\n) { // handle interface block if(YY_START == Start) { addModule(NULL); @@ -417,7 +423,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA yy_push_state(InterfaceBody); startScope(last_entry); } -<InterfaceBody>^{BS}"end"({BS}"interface"({BS_}{ID})?)?{BS}/(\n|!) { +<InterfaceBody>^{BS}"end"({BS}"interface"({BS_}{ID}{ARGS}?)?)?{BS}/(\n|!) { if (!endScope(current_root)) yyterminate(); yy_pop_state(); @@ -1327,6 +1333,16 @@ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) typeName += ","; typeName += "save"; } + if (mdfs.protection == SymbolModifiers::PUBLIC) + { + typeName += ","; + typeName += "public"; + } + else if (mdfs.protection == SymbolModifiers::PRIVATE) + { + typeName += ","; + typeName += "private"; + } return typeName; } @@ -1485,6 +1501,7 @@ static void initEntry() current->mtype = mtype; current->virt = virt; current->stat = gstat; + current->lang = SrcLangExt_F90; initGroupInfo(current); } @@ -1706,11 +1723,13 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) groupEnterFile(yyFileName,yyLineNr); current = new Entry; + current->lang = SrcLangExt_F90; current->name = yyFileName; current->section = Entry::SOURCE_SEC; current_root->addSubEntry(current); file_root = current; current = new Entry; + current->lang = SrcLangExt_F90; fscanYYrestart( fscanYYin ); { diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index cfe229e..81dc753 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -1634,11 +1634,14 @@ void HtmlDocVisitor::writeDotFile(const QCString &fn,const QCString &relPath, writeDotGraphFromFile(fn,outDir,baseName,BITMAP); QCString mapName = baseName+".map"; QCString mapFile = fn+".map"; - m_t << "<img src=\"" << relPath << baseName << "." - << Config_getEnum("DOT_IMAGE_FORMAT") << "\" alt=\"" - << baseName << "\" border=\"0\" usemap=\"#" << mapName << "\">" << endl; - QCString imap = getDotImageMapFromFile(fn,outDir,relPath,context); - m_t << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">" << imap << "</map>" << endl; + //m_t << "<img src=\"" << relPath << baseName << "." + // << Config_getEnum("DOT_IMAGE_FORMAT") << "\" alt=\"" + // << baseName << "\" border=\"0\" usemap=\"#" << mapName << "\">" + // << endl; + //QCString imap = getDotImageMapFromFile(m_t,fn,baseName,outDir,relPath,context); + //m_t << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">" + // << imap << "</map>" << endl; + writeDotImageMapFromFile(m_t,fn,outDir,relPath,context); } void HtmlDocVisitor::writeMscFile(const QCString &fileName,const QCString &relPath, diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index e682583..1c0596c 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -43,8 +43,8 @@ #include "image.h" -//#define DBG_HTML(x) x; -#define DBG_HTML(x) +#define DBG_HTML(x) x; +//#define DBG_HTML(x) static const char defaultStyleSheet[] = #include "doxygen_css.h" diff --git a/src/index.cpp b/src/index.cpp index 306f831..8031f56 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -3141,7 +3141,15 @@ void writeGraphInfo(OutputList &ol) bool oldStripCommentsState = stripCommentsStateRef; // temporarily disable the stripping of comments for our own code example! stripCommentsStateRef = FALSE; - ol.parseDoc("graph_legend",1,0,0,theTranslator->trLegendDocs(),FALSE,FALSE); + QCString legendDocs = theTranslator->trLegendDocs(); + int s = legendDocs.find("<center>"); + int e = legendDocs.find("</center>"); + if (Config_getEnum("DOT_IMAGE_FORMAT")=="svg" && s!=-1 && e!=-1) + { + legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e); + //printf("legendDocs=%s\n",legendDocs.data()); + } + ol.parseDoc("graph_legend",1,0,0,legendDocs,FALSE,FALSE); stripCommentsStateRef = oldStripCommentsState; endFile(ol); ol.popGeneratorState(); diff --git a/src/index.h b/src/index.h index 93bfee4..986b72c 100644 --- a/src/index.h +++ b/src/index.h @@ -203,7 +203,7 @@ enum NamespaceMemberHighlight NMHL_Typedefs, NMHL_Enums, NMHL_EnumValues, - NMHL_Total = FMHL_EnumValues+1 + NMHL_Total = NMHL_EnumValues+1 }; enum ClassHighlight diff --git a/src/instdox.cpp b/src/instdox.cpp index 692df53..648a5c7 100644 --- a/src/instdox.cpp +++ b/src/instdox.cpp @@ -119,6 +119,7 @@ void writeInstallScript() t << " $match = \"" << Config_getString("HTML_FILE_EXTENSION") << "\";\n"; t << " next if ( $file =~ /^\\.\\.?$/ );\n"; t << " ($file =~ /$match/) && (push @files, $file);\n"; + t << " ($file =~ /\\.svg/) && (push @files, $file);\n"; t << " ($file =~ \"tree.js\") && (push @files, $file);\n"; t << " }\n"; t << " closedir(D);\n"; @@ -147,7 +148,7 @@ void writeInstallScript() t << " }\n"; t << " if ($oldf ne \"tree.js\") {\n"; t << " while (<F>) {\n"; - t << " s/doxygen\\=\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\" (href|src)=\\\"\\2/doxygen\\=\\\"$1:$subst{$1}\\\" \\3=\\\"$subst{$1}/g;\n"; + t << " s/doxygen\\=\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\" (xlink:href|href|src)=\\\"\\2/doxygen\\=\\\"$1:$subst{$1}\\\" \\3=\\\"$subst{$1}/g;\n"; t << " print G \"$_\";\n"; t << " }\n"; t << " }\n"; diff --git a/src/layout.cpp b/src/layout.cpp index a0b9a6b..f2b3b4a 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -769,6 +769,8 @@ class LayoutParser : public QXmlDefaultHandler bool javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + bool hasGraphicalHierarchy = Config_getBool("HAVE_DOT") && + Config_getBool("GRAPHICAL_HIERARCHY"); static struct NavEntryMap { const char *typeStr; // type attribute name in the XML file @@ -799,7 +801,8 @@ class LayoutParser : public QXmlDefaultHandler theTranslator->trClasses(), theTranslator->trCompoundList(), "annotated" }, { "hierarchy", LayoutNavEntry::ClassHierarchy, vhdlOpt ? VhdlDocGen::trDesignUnitHierarchy() : - theTranslator->trClassHierarchy(), QCString(), "hierarchy" }, + theTranslator->trClassHierarchy(), QCString(), + hasGraphicalHierarchy ? "inherits" : "hierarchy" }, { "classmembers", LayoutNavEntry::ClassMembers, fortranOpt ? theTranslator->trCompoundMembersFortran() : vhdlOpt ? VhdlDocGen::trDesignUnitMembers() : theTranslator->trCompoundMembers(), QCString(), "functions" }, diff --git a/src/memberlist.cpp b/src/memberlist.cpp index fddb0b4..ca034d7 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -422,7 +422,7 @@ void MemberList::writeDeclarations(OutputList &ol, if (!st.isEmpty()) { ol.startMemberSubtitle(); - ol.parseDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE); + ol.parseDoc("[generated]",-1,ctx,0,subtitle,FALSE,FALSE,0,TRUE,FALSE); ol.endMemberSubtitle(); } } diff --git a/src/scanner.l b/src/scanner.l index 4846433..be8f716 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -4733,19 +4733,27 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) BEGIN( ClassVar ); } <ClassVar>":" { - current->type.resize(0); - if ((current->spec & Entry::Interface) || - (current->spec & Entry::Struct) || - (current->spec & Entry::Ref) || - (current->spec & Entry::Value) || - insidePHP || insideCS || insideD || insideObjC - ) - baseProt=Public; + if (current->section == Entry::VARIABLE_SEC) // enum a b:2, see bug 313527 + { + BEGIN(BitFields); + current->bitfields+=":"; + } else - baseProt=Private; - baseVirt=Normal; - baseName.resize(0); - BEGIN( BasesProt ) ; + { + current->type.resize(0); + if ((current->spec & Entry::Interface) || + (current->spec & Entry::Struct) || + (current->spec & Entry::Ref) || + (current->spec & Entry::Value) || + insidePHP || insideCS || insideD || insideObjC + ) + baseProt=Public; + else + baseProt=Private; + baseVirt=Normal; + baseName.resize(0); + BEGIN( BasesProt ) ; + } } <ClassVar>[;=*&] { unput(*yytext); diff --git a/src/translator_nl.h b/src/translator_nl.h index 595f944..7688882 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -33,9 +33,6 @@ class TranslatorDutch : public Translator * "\\usepackage[latin2]{inputenc}\n" * "\\usepackage[T1]{fontenc}\n" * </pre> - * - * The Dutch LaTeX does not use such commands. Because of this - * the empty string is returned in this implementation. */ QCString latexLanguageSupportCommand() { @@ -90,11 +87,11 @@ class TranslatorDutch : public Translator QCString trCompoundList() { return "Klasse Lijst"; } QCString trFileList() - { return "File Lijst"; } + { return "Bestandslijst"; } QCString trCompoundMembers() { return "Klasse Members"; } QCString trFileMembers() - { return "File members"; } + { return "Bestand members"; } QCString trRelatedPages() { return "Gerelateerde pagina's"; } QCString trExamples() @@ -150,13 +147,13 @@ class TranslatorDutch : public Translator QCString trCompoundIndex() { return "Klasse Index"; } QCString trFileIndex() - { return "File Index"; } + { return "Bestand Index"; } QCString trModuleDocumentation() { return "Module Documentatie"; } QCString trClassDocumentation() { return "Klassen Documentatie"; } QCString trFileDocumentation() - { return "File Documentatie"; } + { return "Bestand Documentatie"; } QCString trExampleDocumentation() { return "Documentatie van voorbeelden"; } QCString trPageDocumentation() @@ -1145,7 +1142,7 @@ class TranslatorDutch : public Translator * and the fact that it is sorted alphabetically per level */ virtual QCString trDirDescription() - { return "Deze directory hiërarchie is min of meer alfabetisch " + { return "Deze folder hiërarchie is min of meer alfabetisch " "gesorteerd:"; } @@ -1191,7 +1188,7 @@ class TranslatorDutch : public Translator /*! header that is put before the list of member subprograms (Fortran). */ virtual QCString trMemberFunctionDocumentationFortran() - { return "Member Function/Subroutine Documentation"; } + { return "Member Funcie/Subroutine Documentatie"; } ////////////////////////////////////////////////////////////////////////// // new since 1.5.4 (mainly for Fortran) diff --git a/src/util.cpp b/src/util.cpp index b2d026f..c9967ae 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3194,6 +3194,7 @@ static QCString getCanonicalTypeForIdentifier( } if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations + //printf("cd=%p mtype=%p\n",cd,mType); //printf(" getCanonicalTypeForIdentifer: symbol=%s word=%s cd=%s d=%s fs=%s cd->isTemplate=%d\n", // symName.data(), // word.data(), @@ -3264,7 +3265,8 @@ static QCString getCanonicalTypeForIdentifier( } else if (mType && mType->isTypedef()) // a typedef { - result = mType->qualifiedName(); + //result = mType->qualifiedName(); // changed after 1.7.2 + result = mType->typeString(); } else // fallback { diff --git a/src/vhdlscanner.h b/src/vhdlscanner.h index 9f3a15c..2523990 100644 --- a/src/vhdlscanner.h +++ b/src/vhdlscanner.h @@ -32,21 +32,6 @@ #include "entry.h" #include "memberlist.h" -#if 0 -#include "qcstring.h" -#include "qlist.h" -#include "qstringlist.h" -#include "filedef.h" -#include "classlist.h" -#include "classdef.h" -#include "translator.h" -#include "qregexp.h" -#include "outputlist.h" -#include "membername.h" -#include "memberdef.h" -#include "memberlist.h" -#endif - class Entry; class ClassSDict; class FileStorage; diff --git a/src/vhdlscanner.l b/src/vhdlscanner.l index e9704ec..2e6f0ab 100644 --- a/src/vhdlscanner.l +++ b/src/vhdlscanner.l @@ -176,7 +176,7 @@ static void deleteSpecChars(char* str,char *buf) *buf='\0'; } -void getType(Entry* p,char* text) +static void getType(Entry* p,char* text) { QCString name(text); name=name.stripWhiteSpace(); @@ -241,7 +241,7 @@ void getType(Entry* p,char* text) * adds signals found in entities|records|units */ -void addSignals(const char* str,int line, Entry *e,const char *comment=0) +static void addSignals(const char* str,int line, Entry *e,const char *comment=0) { //printf("===> addSignals (%s) comment='%s'\n",str,comment); QList<QCString> ql; @@ -492,8 +492,7 @@ static Entry* getEntryAtLine(const Entry* ce,int line) //------------------------------------------------------------------------- - -void parserInit() +static void parserInit() { iCounter=0; iTextCounter=0; @@ -1803,7 +1802,7 @@ static void mergeGrouping(const Entry* ce,int) * and so on.. */ -void mapLibPackage(const Entry* ce) +static void mapLibPackage(const Entry* ce) { Entry *lastComp=0; while (TRUE) |