summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml17
-rw-r--r--CMakeLists.txt12
-rw-r--r--Doxyfile1
-rw-r--r--README.md2
-rw-r--r--addon/doxmlparser/CMakeLists.txt4
-rw-r--r--addon/doxmlparser/Doxyfile1
-rw-r--r--addon/doxmlparser/Doxyfile.impl1
-rw-r--r--addon/doxmlparser/examples/CMakeLists.txt2
-rw-r--r--addon/doxmlparser/examples/metrics/CMakeLists.txt14
-rw-r--r--addon/doxmlparser/examples/metrics/Makefile.in15
-rw-r--r--addon/doxmlparser/examples/metrics/metrics.pro.in20
-rw-r--r--[l---------]addon/doxmlparser/include/doxmlintf.h1142
-rw-r--r--addon/doxmlparser/src/CMakeLists.txt18
-rw-r--r--addon/doxmlparser/src/compoundhandler.cpp1
-rw-r--r--addon/doxmlparser/src/compoundhandler.h2
-rw-r--r--addon/doxmlparser/src/doxmlintf.h1141
-rw-r--r--addon/doxmlparser/src/loamhandler.cpp2
-rw-r--r--addon/doxmlparser/src/mainhandler.cpp2
-rw-r--r--addon/doxmlparser/src/sectionhandler.cpp2
-rw-r--r--addon/doxmlparser/test/CMakeLists.txt15
-rw-r--r--addon/doxmlparser/test/Makefile.in15
-rw-r--r--addon/doxmlparser/test/xmlparse.pro.in20
-rw-r--r--addon/doxyapp/CMakeLists.txt15
-rw-r--r--addon/doxyapp/doxyapp.cpp2
-rw-r--r--addon/doxyparse/CMakeLists.txt15
-rw-r--r--addon/doxyparse/doxyparse.cpp31
-rw-r--r--addon/doxysearch/doxysearch.cpp22
-rw-r--r--appveyor.yml24
-rw-r--r--doc/Doxyfile1
-rw-r--r--doc/commands.doc49
-rw-r--r--doc/docblocks.doc19
-rw-r--r--doc/doxygen_manual.tex68
-rw-r--r--doc/faq.doc7
-rw-r--r--doc/install.doc2
-rw-r--r--doc/trouble.doc2
-rw-r--r--examples/CMakeLists.txt8
-rw-r--r--examples/javadoc-banner.cfg15
-rw-r--r--examples/javadoc-banner.h45
-rw-r--r--examples/tag.cfg1
-rw-r--r--jquery/Makefile4
-rw-r--r--jquery/README8
-rw-r--r--jquery/jquery-3.3.1.min.js2
-rw-r--r--jquery/jquery-3.4.1.min.js2
-rw-r--r--jquery/jquery.powertip-1.3.1.min.js8
-rw-r--r--jquery/jquery.powertip-1.3.1.mod.js1324
-rw-r--r--jquery/jquery.powertip-1.3.1.mod.min.js8
-rw-r--r--liblodepng/CMakeLists.txt3
-rw-r--r--liblodepng/lodepng.cpp (renamed from src/lodepng.cpp)4
-rw-r--r--liblodepng/lodepng.h (renamed from src/lodepng.h)8
-rw-r--r--libmd5/Makefile.in18
-rw-r--r--libmd5/libmd5.pro.in10
-rw-r--r--libmscgen/CMakeLists.txt38
-rw-r--r--libmscgen/COPYING287
-rw-r--r--libmscgen/README.txt20
-rw-r--r--libmscgen/gd.c4539
-rw-r--r--libmscgen/gd.h1620
-rw-r--r--libmscgen/gd_color.c35
-rw-r--r--libmscgen/gd_color.h14
-rw-r--r--libmscgen/gd_errors.h46
-rw-r--r--libmscgen/gd_intern.h78
-rw-r--r--libmscgen/gd_lodepng.c35
-rw-r--r--libmscgen/gd_security.c32
-rw-r--r--libmscgen/gdfonts.c3890
-rw-r--r--libmscgen/gdfonts.h27
-rw-r--r--libmscgen/gdfontt.c2613
-rw-r--r--libmscgen/gdfontt.h28
-rw-r--r--libmscgen/gdhelpers.c118
-rw-r--r--libmscgen/gdhelpers.h76
-rw-r--r--libmscgen/gdtables.c726
-rw-r--r--libmscgen/mscgen_adraw.c140
-rw-r--r--libmscgen/mscgen_adraw.h300
-rw-r--r--libmscgen/mscgen_adraw_int.h65
-rw-r--r--libmscgen/mscgen_api.c1874
-rw-r--r--libmscgen/mscgen_api.h41
-rw-r--r--libmscgen/mscgen_bool.h36
-rw-r--r--libmscgen/mscgen_config.h55
-rw-r--r--libmscgen/mscgen_gd_out.c606
-rw-r--r--libmscgen/mscgen_language.h186
-rw-r--r--libmscgen/mscgen_language.y430
-rw-r--r--libmscgen/mscgen_lexer.h62
-rw-r--r--libmscgen/mscgen_lexer.l236
-rw-r--r--libmscgen/mscgen_msc.c804
-rw-r--r--libmscgen/mscgen_msc.h299
-rw-r--r--libmscgen/mscgen_null_out.c170
-rw-r--r--libmscgen/mscgen_ps_out.c595
-rw-r--r--libmscgen/mscgen_safe.c119
-rw-r--r--libmscgen/mscgen_safe.h59
-rw-r--r--libmscgen/mscgen_svg_out.c585
-rw-r--r--libmscgen/mscgen_usage.c111
-rw-r--r--libmscgen/mscgen_usage.h49
-rw-r--r--libmscgen/mscgen_utf8.c103
-rw-r--r--libmscgen/mscgen_utf8.h48
-rw-r--r--qtools/Doxyfile1
-rw-r--r--src/CMakeLists.txt24
-rw-r--r--src/clangparser.cpp2
-rw-r--r--src/classdef.cpp589
-rw-r--r--src/classdef.h106
-rw-r--r--src/classlist.cpp6
-rw-r--r--src/classlist.h4
-rw-r--r--src/code.h2
-rw-r--r--src/code.l171
-rw-r--r--src/commentcnv.l29
-rw-r--r--src/commentscan.h8
-rw-r--r--src/commentscan.l306
-rw-r--r--src/config.xml38
-rw-r--r--src/configimpl.l28
-rw-r--r--src/constexp.h23
-rw-r--r--src/constexp.l85
-rw-r--r--src/constexp.y44
-rw-r--r--src/context.cpp324
-rw-r--r--src/context.h80
-rw-r--r--src/cppvalue.cpp32
-rw-r--r--src/cppvalue.h11
-rw-r--r--src/declinfo.l311
-rw-r--r--src/defgen.cpp9
-rw-r--r--src/definition.cpp51
-rw-r--r--src/definition.h60
-rw-r--r--src/definitionimpl.h184
-rw-r--r--src/dia.cpp2
-rw-r--r--src/diagram.cpp20
-rw-r--r--src/diagram.h2
-rw-r--r--src/dirdef.cpp5
-rw-r--r--src/dirdef.h8
-rw-r--r--src/docbookgen.cpp33
-rw-r--r--src/docbookgen.h18
-rw-r--r--src/docbookvisitor.cpp84
-rw-r--r--src/docbookvisitor.h2
-rw-r--r--src/docgroup.cpp212
-rw-r--r--src/docgroup.h54
-rw-r--r--src/docparser.cpp527
-rw-r--r--src/docparser.h36
-rw-r--r--src/docsets.cpp18
-rw-r--r--src/docsets.h4
-rw-r--r--src/doctokenizer.h4
-rw-r--r--src/doctokenizer.l13
-rw-r--r--src/docvisitor.h3
-rw-r--r--src/dot.cpp4573
-rw-r--r--src/dot.h484
-rw-r--r--src/dotcallgraph.cpp217
-rw-r--r--src/dotcallgraph.h52
-rw-r--r--src/dotclassgraph.cpp548
-rw-r--r--src/dotclassgraph.h62
-rw-r--r--src/dotdirdeps.cpp220
-rw-r--r--src/dotdirdeps.h51
-rw-r--r--src/dotfilepatcher.cpp539
-rw-r--r--src/dotfilepatcher.h53
-rw-r--r--src/dotgfxhierarchytable.cpp302
-rw-r--r--src/dotgfxhierarchytable.h55
-rw-r--r--src/dotgraph.cpp400
-rw-r--r--src/dotgraph.h113
-rw-r--r--src/dotgroupcollaboration.cpp381
-rw-r--r--src/dotgroupcollaboration.h85
-rw-r--r--src/dotincldepgraph.cpp238
-rw-r--r--src/dotincldepgraph.h56
-rw-r--r--src/dotnode.cpp950
-rw-r--r--src/dotnode.h138
-rw-r--r--src/dotrunner.cpp294
-rw-r--r--src/dotrunner.h138
-rw-r--r--src/doxygen.cpp659
-rw-r--r--src/doxygen.h8
-rw-r--r--src/eclipsehelp.cpp6
-rw-r--r--src/eclipsehelp.h4
-rw-r--r--src/entry.h4
-rw-r--r--src/filedef.cpp51
-rw-r--r--src/filedef.h10
-rw-r--r--src/fileparser.cpp4
-rw-r--r--src/fileparser.h4
-rw-r--r--src/fortrancode.h2
-rw-r--r--src/fortrancode.l22
-rw-r--r--src/fortranscanner.h4
-rw-r--r--src/fortranscanner.l20
-rw-r--r--src/ftvhelp.cpp32
-rw-r--r--src/ftvhelp.h4
-rw-r--r--src/groupdef.cpp51
-rw-r--r--src/groupdef.h5
-rw-r--r--src/htags.cpp6
-rw-r--r--src/htmldocvisitor.cpp18
-rw-r--r--src/htmldocvisitor.h6
-rw-r--r--src/htmlgen.cpp57
-rw-r--r--src/htmlgen.h22
-rw-r--r--src/htmlhelp.cpp4
-rw-r--r--src/htmlhelp.h4
-rw-r--r--src/index.cpp36
-rw-r--r--src/index.h16
-rw-r--r--src/latexdocvisitor.cpp16
-rw-r--r--src/latexdocvisitor.h2
-rw-r--r--src/latexgen.cpp38
-rw-r--r--src/latexgen.h18
-rw-r--r--src/layout.cpp7
-rw-r--r--src/layout.h2
-rw-r--r--src/mandocvisitor.cpp20
-rw-r--r--src/mandocvisitor.h2
-rw-r--r--src/mangen.cpp2
-rw-r--r--src/mangen.h16
-rw-r--r--src/markdown.cpp101
-rw-r--r--src/markdown.h4
-rw-r--r--src/memberdef.cpp1086
-rw-r--r--src/memberdef.h117
-rw-r--r--src/membergroup.cpp85
-rw-r--r--src/membergroup.h35
-rw-r--r--src/memberlist.cpp223
-rw-r--r--src/memberlist.h34
-rw-r--r--src/membername.cpp16
-rw-r--r--src/message.cpp20
-rw-r--r--src/msc.cpp76
-rw-r--r--src/namespacedef.cpp231
-rw-r--r--src/namespacedef.h26
-rw-r--r--src/outputgen.h16
-rw-r--r--src/outputlist.cpp18
-rw-r--r--src/outputlist.h32
-rw-r--r--src/pagedef.cpp4
-rw-r--r--src/parserintf.h4
-rw-r--r--src/perlmodgen.cpp96
-rw-r--r--src/portable.cpp13
-rw-r--r--src/portable.h1
-rw-r--r--src/pre.l19
-rw-r--r--src/printdocvisitor.h10
-rw-r--r--src/pycode.h2
-rw-r--r--src/pycode.l60
-rw-r--r--src/pyscanner.h4
-rw-r--r--src/pyscanner.l40
-rw-r--r--src/qhp.cpp4
-rw-r--r--src/qhp.h4
-rw-r--r--src/rtfdocvisitor.cpp22
-rw-r--r--src/rtfdocvisitor.h2
-rw-r--r--src/rtfgen.cpp37
-rw-r--r--src/rtfgen.h22
-rw-r--r--src/scanner.h4
-rw-r--r--src/scanner.l102
-rw-r--r--src/searchindex.cpp51
-rw-r--r--src/searchindex.h10
-rw-r--r--src/sqlcode.h2
-rw-r--r--src/sqlcode.l489
-rw-r--r--src/sqlite3gen.cpp20
-rw-r--r--src/sqlscanner.h4
-rw-r--r--src/tclscanner.h4
-rw-r--r--src/tclscanner.l14
-rw-r--r--src/textdocvisitor.h2
-rw-r--r--src/tooltip.cpp2
-rw-r--r--src/tooltip.h2
-rw-r--r--src/util.cpp351
-rw-r--r--src/util.h99
-rw-r--r--src/vhdlcode.h2
-rw-r--r--src/vhdlcode.l12
-rw-r--r--src/vhdldocgen.cpp113
-rw-r--r--src/vhdldocgen.h20
-rw-r--r--src/vhdljjparser.cpp4
-rw-r--r--src/vhdljjparser.h4
-rw-r--r--src/xmlcode.h2
-rw-r--r--src/xmlcode.l9
-rw-r--r--src/xmldocvisitor.cpp20
-rw-r--r--src/xmldocvisitor.h2
-rw-r--r--src/xmlgen.cpp80
-rw-r--r--src/xmlgen.h2
-rw-r--r--src/xmlscanner.h4
-rw-r--r--templates/html/jquery.js6
-rw-r--r--templates/latex/doxygen.sty19
-rwxr-xr-xtemplates/latex/longtable_doxygen.sty448
-rwxr-xr-xtemplates/latex/tabu_doxygen.sty2557
-rw-r--r--templates/xml/compound.xsd29
-rw-r--r--testing/011/interface_integer.xml12
-rw-r--r--testing/019/group__g1.xml2
-rw-r--r--testing/019/group__g2.xml2
-rw-r--r--testing/019/group__g3.xml2
-rw-r--r--testing/021/indexpage.xml2
-rw-r--r--testing/027/struct_car.xml24
-rw-r--r--testing/027/struct_object.xml14
-rw-r--r--testing/027/struct_truck.xml24
-rw-r--r--testing/027/struct_vehicle.xml22
-rw-r--r--testing/071/namespace_a_namespace_1_1_0d0.xml (renamed from testing/071/namespace_a_namespace_1_1_0D0.xml)2
-rw-r--r--testing/071_enum_in_anon_ns.cpp2
-rwxr-xr-xtesting/runtests.py5
-rw-r--r--vhdlparser/CMakeLists.txt12
-rw-r--r--vhdlparser/VhdlParserTokenManager.cc2
274 files changed, 37372 insertions, 9781 deletions
diff --git a/.travis.yml b/.travis.yml
index 4d42ce2..48dcff4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -46,6 +46,8 @@ jobs:
homebrew:
packages:
- ghostscript
+ - bison
+ - flex
casks:
- mactex-no-gui
@@ -54,15 +56,14 @@ before_script:
if [ "${TRAVIS_OS_NAME}" == "linux" ] && [ ! "${OS_NAME}" == "linux-ppc64le" ]; then
printf "[requires]
libxml2/2.9.8@bincrafters/stable
- libiconv/1.15@bincrafters/stable
- [build_requires]
- cmake_installer/3.10.0@conan/stable" >> conanfile.txt;
+ libiconv/1.15@bincrafters/stable" >> conanfile.txt;
fi;
if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
printf "[requires]
libxml2/2.9.8@bincrafters/stable
libiconv/1.15@bincrafters/stable
qt/5.12.0@bincrafters/stable
+ bison/3.0.5@bincrafters/stable
[options]
qt:shared=True" >> conanfile.txt;
fi;
@@ -79,7 +80,9 @@ before_script:
mv epstopdf/epstopdf.pl /Users/travis/Library/TeX/texbin/epstopdf;
chmod a+x /Users/travis/Library/TeX/texbin/epstopdf;
rm -rf epstopdf*;
- export PATH=/Users/travis/Library/TeX/texbin:/Library/TeX/texbin:$PATH;
+ export CMAKE_INCLUDE_PATH="/usr/local/opt/flex/include;$CMAKE_INCLUDE_PATH";
+ export CMAKE_LIBRARY_PATH="/usr/local/opt/flex/lib;/usr/local/opt/bison/lib;$CMAKE_LIBRARY_PATH";
+ export PATH="/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:/Users/travis/Library/TeX/texbin:/Library/TeX/texbin:$PATH";
fi;
- if [ ! "${OS_NAME}" == "linux-ppc64le" ]; then
conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan;
@@ -93,5 +96,7 @@ script:
- cmake --version;
- cmake -G "Unix Makefiles" -Dbuild_doc=ON -Dbuild_wizard=ON ..
- make
- - make tests
- - make docs
+ - if [ ! "${TRAVIS_OS_NAME}" == "osx" ]; then
+ make tests;
+ make docs;
+ fi;
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 05ab57b..2621844 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,6 +26,8 @@ option(win_static "Link with /MT in stead of /MD on windows" OFF)
option(english_only "Only compile in support for the English language" OFF)
option(force_qt4 "Forces doxywizard to build using Qt4 even if Qt5 is installed" OFF)
+SET(enlarge_lex_buffers "262144" CACHE INTERNAL "Sets the lex input and read buffere to the specified size")
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
set(TOP "${CMAKE_SOURCE_DIR}")
include(version)
@@ -46,6 +48,11 @@ if (use_libclang)
endif()
endif()
+# use C++11 standard for compiling (libclang option requires it)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
if (CMAKE_SYSTEM MATCHES "Darwin")
set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_C_FLAGS}")
@@ -83,6 +90,9 @@ find_program(DOT NAMES dot)
find_package(PythonInterp REQUIRED)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
+if (BISON_VERSION VERSION_LESS 2.7)
+ message(SEND_ERROR "Doxygen requires at least bison version 2.7 (installed: ${BISON_VERSION})")
+endif()
find_package(Threads)
if (sqlite3)
@@ -143,6 +153,8 @@ endif()
add_subdirectory(libmd5)
+add_subdirectory(liblodepng)
+add_subdirectory(libmscgen)
add_subdirectory(libversion)
add_subdirectory(qtools)
add_subdirectory(vhdlparser)
diff --git a/Doxyfile b/Doxyfile
index 8eabf0e..cc2aca7 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -276,7 +276,6 @@ GENERATE_TAGFILE = doxygen.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
-PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
diff --git a/README.md b/README.md
index 3cc6499..52fd7e9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
Doxygen
===============
+[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9HHLRBCC8B2B8)
+
Doxygen is the de facto standard tool for generating documentation from
annotated C++ sources, but it also supports other popular programming
languages such as C, Objective-C, C#, PHP, Java, Python, IDL
diff --git a/addon/doxmlparser/CMakeLists.txt b/addon/doxmlparser/CMakeLists.txt
index e69de29..8456d2a 100644
--- a/addon/doxmlparser/CMakeLists.txt
+++ b/addon/doxmlparser/CMakeLists.txt
@@ -0,0 +1,4 @@
+
+add_subdirectory(src)
+add_subdirectory(examples)
+add_subdirectory(test)
diff --git a/addon/doxmlparser/Doxyfile b/addon/doxmlparser/Doxyfile
index faf4bee..e95ee76 100644
--- a/addon/doxmlparser/Doxyfile
+++ b/addon/doxmlparser/Doxyfile
@@ -146,7 +146,6 @@ SKIP_FUNCTION_MACROS = YES
TAGFILES = ../../qtools_docs/qtools.tag=../../../../qtools_docs/html
GENERATE_TAGFILE =
ALLEXTERNALS = NO
-PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
diff --git a/addon/doxmlparser/Doxyfile.impl b/addon/doxmlparser/Doxyfile.impl
index a954db3..88818ab 100644
--- a/addon/doxmlparser/Doxyfile.impl
+++ b/addon/doxmlparser/Doxyfile.impl
@@ -148,7 +148,6 @@ TAGFILES = ../../qtools_docs/qtools.tag=../../../../qtools_docs/ht
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
-PERL_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
diff --git a/addon/doxmlparser/examples/CMakeLists.txt b/addon/doxmlparser/examples/CMakeLists.txt
new file mode 100644
index 0000000..1e08d36
--- /dev/null
+++ b/addon/doxmlparser/examples/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+add_subdirectory(metrics)
diff --git a/addon/doxmlparser/examples/metrics/CMakeLists.txt b/addon/doxmlparser/examples/metrics/CMakeLists.txt
new file mode 100644
index 0000000..8e03246
--- /dev/null
+++ b/addon/doxmlparser/examples/metrics/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+include_directories(
+ ../../include
+)
+
+add_executable(doxmlparser_metrics
+main.cpp
+)
+
+
+target_link_libraries(doxmlparser_metrics
+ doxmlparser
+ qtools
+)
diff --git a/addon/doxmlparser/examples/metrics/Makefile.in b/addon/doxmlparser/examples/metrics/Makefile.in
deleted file mode 100644
index a3eb784..0000000
--- a/addon/doxmlparser/examples/metrics/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-all clean depend: Makefile.metrics
- $(MAKE) -f Makefile.metrics $@
-
-distclean: clean
- $(RM) -rf Makefile.metrics metrics.pro Makefile obj
-
-realclean: distclean
-
-tmake:
- $(ENV) $(PERL) $(TMAKE) metrics.pro >Makefile.metrics
-
-Makefile.metrics: metrics.pro
- $(ENV) $(PERL) $(TMAKE) metrics.pro >Makefile.metrics
-
-install:
diff --git a/addon/doxmlparser/examples/metrics/metrics.pro.in b/addon/doxmlparser/examples/metrics/metrics.pro.in
deleted file mode 100644
index 3b2354d..0000000
--- a/addon/doxmlparser/examples/metrics/metrics.pro.in
+++ /dev/null
@@ -1,20 +0,0 @@
-TEMPLATE = app.t
-CONFIG = console warn_on $extraopts
-HEADERS =
-SOURCES = main.cpp
-unix:LIBS += -L../../../../lib -ldoxmlparser -lqtools
-win32:INCLUDEPATH += .
-win32-mingw:LIBS += -L../../../../lib -ldoxmlparser -lqtools
-win32-msvc:LIBS += doxmlparser.lib qtools.lib shell32.lib
-win32-msvc:TMAKE_LFLAGS += /LIBPATH:..\..\..\..\lib;
-win32-borland:LIBS += doxmlparser.lib qtools.lib shell32.lib
-win32-borland:TMAKE_LFLAGS += -L..\..\..\..\lib
-win32:TMAKE_CXXFLAGS += -DQT_NODLL
-DESTDIR = ../../../../bin
-OBJECTS_DIR = ../../../../objects/doxmlparer/metrics
-TARGET = metrics
-DEPENDPATH = ../../include
-INCLUDEPATH += ../../../../qtools ../../include
-unix:TARGETDEPS = ../../../../lib/libdoxmlparser.a
-win32:TARGETDEPS = ..\..\..\..\lib\doxmlparser.lib
-
diff --git a/addon/doxmlparser/include/doxmlintf.h b/addon/doxmlparser/include/doxmlintf.h
index 2d2b707..22cecdb 120000..100644
--- a/addon/doxmlparser/include/doxmlintf.h
+++ b/addon/doxmlparser/include/doxmlintf.h
@@ -1 +1,1141 @@
-../src/doxmlintf.h \ No newline at end of file
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-2015 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.
+ *
+ */
+
+#ifndef _DOXMLINTF_H
+#define _DOXMLINTF_H
+
+/*! \file
+ * \brief The interface to the object model provided by the XML parser
+ * library.
+ *
+ * To start using this library one calls createObjectModel() and then
+ * uses the returned IDoxygen interface to read doxygen generated
+ * XML output and navigate through the information contained in it.
+ *
+ * @see createObjectModel()
+ */
+
+class IMember;
+class IDocIterator;
+class ICompound;
+class ISection;
+class INode;
+class IDocInternal;
+class IDocRoot;
+
+#define VIRTUAL_DESTRUCTOR(x) virtual ~x() {}
+
+/*! \brief Read only interface to a string.
+ */
+class IString
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IString)
+ /*! Returns a latin1 character representation of the string. */
+ virtual const char *latin1() const = 0;
+ /*! Returns a utf8 character representation of the string. */
+ virtual const char *utf8() const = 0;
+ /*! Returns a 16-bit unicode character representation of the character at
+ * position \a index in the string. The first character is at index 0.
+ */
+ virtual unsigned short unicodeCharAt(int index) const = 0;
+ /*! Returns true if this string is empty or false otherwise */
+ virtual bool isEmpty() const = 0;
+ /*! Returns the number of characters in the string. */
+ virtual int length() const = 0;
+};
+
+/*! \brief Base interface for hyperlinked text
+ *
+ * Depending on the result of kind() the interface is extended by
+ * ILT_Text or ILT_Ref.
+ */
+class ILinkedText
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ILinkedText)
+ enum Kind { Kind_Text, Kind_Ref };
+ virtual Kind kind() const = 0;
+};
+
+/*! \brief Plain text fragment.
+ */
+class ILT_Text : public ILinkedText
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ILT_Text)
+ virtual const IString *text() const = 0;
+};
+
+/*! \brief Reference to an object.
+ */
+class ILT_Ref : public ILinkedText
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ILT_Ref)
+ enum TargetKind { Member, Compound };
+ virtual const IString *id() const = 0;
+ virtual TargetKind targetKind() const = 0;
+ virtual const IString *external() const = 0;
+ virtual const IString *text() const = 0;
+};
+
+/*! \brief Iterates over a list of ILinkedText fragments.
+ */
+class ILinkedTextIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ILinkedTextIterator)
+ virtual ILinkedText *toFirst() = 0;
+ virtual ILinkedText *toLast() = 0;
+ virtual ILinkedText *toNext() = 0;
+ virtual ILinkedText *toPrev() = 0;
+ virtual ILinkedText *current() const = 0;
+ virtual void release() = 0;
+};
+
+/*! \brief Representation of a parameter of a function. */
+class IParam
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IParam)
+ virtual ILinkedTextIterator *type() const = 0;
+ virtual const IString * declarationName() const = 0;
+ virtual const IString * definitionName() const = 0;
+ virtual const IString * attrib() const = 0;
+ virtual const IString * arraySpecifier() const = 0;
+ virtual ILinkedTextIterator *defaultValue() const = 0;
+ virtual IDocRoot *briefDescription() const = 0;
+};
+
+class IParamIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IParamIterator)
+ virtual IParam *toFirst() = 0;
+ virtual IParam *toLast() = 0;
+ virtual IParam *toNext() = 0;
+ virtual IParam *toPrev() = 0;
+ virtual IParam *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IMemberReference
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IMemberReference)
+ virtual IMember *member() const = 0;
+ virtual const IString * name() const = 0;
+ virtual const IString * scope() const = 0;
+ virtual const IString * protection() const = 0;
+ virtual const IString * virtualness() const = 0;
+ virtual const IString * ambiguityScope() const = 0;
+};
+
+class IMemberReferenceIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IMemberReferenceIterator)
+ virtual IMemberReference *toFirst() = 0;
+ virtual IMemberReference *toLast() = 0;
+ virtual IMemberReference *toNext() = 0;
+ virtual IMemberReference *toPrev() = 0;
+ virtual IMemberReference *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IDoc
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IDoc)
+ enum Kind
+ {
+ Invalid = 0, // 0
+ Para, // 1 -> IDocPara
+ Text, // 2 -> IDocText
+ MarkupModifier, // 3 -> IDocMarkupModifier
+ ItemizedList, // 4 -> IDocItemizedList
+ OrderedList, // 5 -> IDocOrderedList
+ ListItem, // 6 -> IDocListItem
+ ParameterList, // 7 -> IDocParameterList
+ Parameter, // 8 -> IDocParameter
+ SimpleSect, // 9 -> IDocSimpleSect
+ Title, // 10 -> IDocTitle
+ Ref, // 11 -> IDocRef
+ VariableList, // 12 -> IDocVariableList
+ VariableListEntry, // 13 -> IDocVariableListEntry
+ HRuler, // 14 -> IDocHRuler
+ LineBreak, // 15 -> IDocLineBreak
+ ULink, // 16 -> IDocULink
+ EMail, // 17 -> IDocEMail
+ Link, // 18 -> IDocLink
+ ProgramListing, // 19 -> IDocProgramListing
+ CodeLine, // 20 -> IDocCodeLine
+ Highlight, // 21 -> IDocHighlight
+ Formula, // 22 -> IDocFormula
+ Image, // 23 -> IDocImage
+ DotFile, // 24 -> IDocDotFile
+ IndexEntry, // 25 -> IDocIndexEntry
+ Table, // 26 -> IDocTable
+ Row, // 27 -> IDocRow
+ Entry, // 28 -> IDocEntry
+ Section, // 29 -> IDocSection
+ Verbatim, // 30 -> IDocVerbatim
+ Copy, // 31 -> IDocCopy
+ TocList, // 32 -> IDocTocList
+ TocItem, // 33 -> IDocTocItem
+ Anchor, // 34 -> IDocAnchor
+ Symbol, // 35 -> IDocSymbol
+ Internal, // 36 -> IDocInternal
+ Root, // 37 -> IDocRoot
+ ParameterItem // 38 -> IDocParameterItem
+ };
+ virtual Kind kind() const = 0;
+};
+
+class IDocMarkup : public IDoc
+{
+ public:
+ enum Markup
+ {
+ Normal = 0x000,
+ Bold = 0x001,
+ Emphasis = 0x002,
+ ComputerOutput = 0x004,
+ Subscript = 0x008,
+ Superscript = 0x010,
+ SmallFont = 0x020,
+ Center = 0x040,
+ Preformatted = 0x080,
+ Heading = 0x100
+ };
+};
+
+class IDocPara : public IDoc
+{
+ public:
+ virtual IDocIterator *contents() const = 0;
+};
+
+class IDocText : public IDocMarkup
+{
+ public:
+ virtual const IString * text() const = 0;
+ virtual int markup() const = 0;
+ virtual int headingLevel() const = 0;
+};
+
+class IDocMarkupModifier : public IDoc
+{
+ public:
+ virtual bool enabled() const = 0;
+ virtual int markup() const = 0;
+ virtual int headingLevel() const = 0;
+};
+
+class IDocItemizedList : public IDoc
+{
+ public:
+ virtual IDocIterator *elements() const = 0;
+};
+
+class IDocOrderedList : public IDoc
+{
+ public:
+ virtual IDocIterator *elements() const = 0;
+};
+
+class IDocListItem : public IDoc
+{
+ public:
+ virtual IDocIterator *contents() const = 0;
+};
+
+class IDocParameterList : public IDoc
+{
+ public:
+ enum Types { Param, RetVal, Exception };
+ virtual Types sectType() const = 0;
+ virtual IDocIterator *params() const = 0;
+};
+
+class IDocParameterItem : public IDoc
+{
+ public:
+ virtual IDocIterator *paramNames() const = 0;
+ virtual IDocPara *description() const = 0;
+};
+
+class IDocParameter : public IDoc
+{
+ public:
+ virtual const IString * name() const = 0;
+};
+
+class IDocTitle : public IDoc
+{
+ public:
+ virtual IDocIterator *title() const = 0;
+};
+
+class IDocSimpleSect : public IDoc
+{
+ public:
+ enum Types { Invalid = 0,
+ See, Return, Author, Version,
+ Since, Date, Bug, Note,
+ Warning, Par, Deprecated, Pre,
+ Post, Invar, Remark, Attention,
+ Todo, Test, RCS, EnumValues,
+ Examples
+ };
+ virtual Types type() const = 0;
+ virtual const IString * typeString() const = 0;
+ virtual IDocTitle *title() const = 0;
+ virtual IDocPara *description() const = 0;
+};
+
+class IDocRef : public IDoc
+{
+ public:
+ enum TargetKind { Member, Compound };
+ virtual const IString * refId() const = 0;
+ virtual TargetKind targetKind() const = 0;
+ virtual const IString * external() const = 0;
+ virtual const IString * text() const = 0;
+};
+
+class IDocVariableList : public IDoc
+{
+ public:
+ virtual IDocIterator *entries() const = 0;
+};
+
+class IDocVariableListEntry : public IDoc
+{
+ public:
+ virtual ILinkedTextIterator * term() const = 0;
+ virtual IDocPara *description() const = 0;
+};
+
+class IDocHRuler : public IDoc
+{
+};
+
+class IDocLineBreak : public IDoc
+{
+};
+
+class IDocULink : public IDoc
+{
+ public:
+ virtual const IString * url() const = 0;
+ virtual const IString * text() const = 0;
+};
+
+class IDocEMail : public IDoc
+{
+ public:
+ virtual const IString * address() const = 0;
+};
+
+class IDocLink : public IDoc
+{
+ public:
+ virtual const IString * refId() const = 0;
+ virtual const IString * text() const = 0;
+};
+
+class IDocProgramListing : public IDoc
+{
+ public:
+ virtual IDocIterator *codeLines() const = 0;
+};
+
+class IDocCodeLine : public IDoc
+{
+ public:
+ virtual int lineNumber() const = 0;
+ virtual const IString * refId() const = 0;
+ virtual IDocIterator *codeElements() const = 0;
+};
+
+class IDocHighlight : public IDoc
+{
+ public:
+ enum HighlightKind
+ { Invalid=0,
+ Comment, Keyword,
+ KeywordType, KeywordFlow, CharLiteral,
+ StringLiteral, Preprocessor
+ };
+ virtual HighlightKind highlightKind() const = 0;
+ virtual IDocIterator *codeElements() const = 0;
+};
+
+class IDocFormula : public IDoc
+{
+ public:
+ virtual const IString * id() const = 0;
+ virtual const IString * text() const = 0;
+};
+
+class IDocImage : public IDoc
+{
+ public:
+ virtual const IString * name() const = 0;
+ virtual const IString * caption() const = 0;
+};
+
+class IDocDotFile : public IDoc
+{
+ public:
+ virtual const IString * name() const = 0;
+ virtual const IString * caption() const = 0;
+};
+
+class IDocIndexEntry : public IDoc
+{
+ public:
+ virtual const IString * primary() const = 0;
+ virtual const IString * secondary() const = 0;
+};
+
+class IDocTable : public IDoc
+{
+ public:
+ virtual IDocIterator *rows() const = 0;
+ virtual int numColumns() const = 0;
+ virtual const IString * caption() const = 0;
+};
+
+class IDocRow : public IDoc
+{
+ public:
+ virtual IDocIterator *entries() const = 0;
+};
+
+class IDocEntry : public IDoc
+{
+ public:
+ virtual IDocIterator *contents() const = 0;
+};
+
+class IDocSection : public IDoc
+{
+ public:
+ virtual const IString * id() const = 0;
+ virtual int level() const = 0;
+ virtual IDocTitle *title() const = 0;
+ virtual IDocIterator *paragraphs() const = 0;
+ virtual IDocIterator *subSections() const = 0;
+ virtual IDocInternal *internal() const = 0;
+};
+
+class IDocInternal : public IDoc
+{
+ public:
+ virtual IDocIterator *paragraphs() const = 0;
+ virtual IDocIterator *subSections() const = 0;
+};
+
+class IDocTocList : public IDoc
+{
+ public:
+ virtual IDocIterator *elements() const = 0;
+};
+
+class IDocTocItem : public IDoc
+{
+ public:
+ virtual const IString *id() const = 0;
+ virtual const IString *title() const = 0;
+};
+
+class IDocCopy : public IDoc
+{
+ public:
+ virtual IDocIterator *contents() const = 0;
+};
+
+class IDocVerbatim : public IDoc
+{
+ public:
+ enum Types { Invalid = 0, HtmlOnly, LatexOnly, Verbatim };
+ virtual const IString *text() const = 0;
+ virtual Types type() const = 0;
+};
+
+class IDocAnchor : public IDoc
+{
+ public:
+ virtual const IString *id() const = 0;
+};
+
+class IDocSymbol : public IDoc
+{
+ public:
+ enum Types
+ { Invalid = 0,
+ Umlaut, Acute, Grave, Circ, Tilde, Szlig, Cedil, Ring, Nbsp, Copy
+ };
+ virtual Types type() const = 0;
+ virtual const IString * typeString() const = 0;
+ virtual char letter() const = 0;
+};
+
+class IDocRoot : public IDoc
+{
+ public:
+ virtual IDocIterator *contents() const = 0;
+ virtual IDocInternal *internal() const = 0;
+};
+
+class IDocIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IDocIterator)
+ virtual IDoc *toFirst() = 0;
+ virtual IDoc *toLast() = 0;
+ virtual IDoc *toNext() = 0;
+ virtual IDoc *toPrev() = 0;
+ virtual IDoc *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IEdgeLabel
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IEdgeLabel)
+ virtual const IString * label() const = 0;
+};
+
+class IEdgeLabelIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IEdgeLabelIterator)
+ virtual IEdgeLabel *toFirst() = 0;
+ virtual IEdgeLabel *toLast() = 0;
+ virtual IEdgeLabel *toNext() = 0;
+ virtual IEdgeLabel *toPrev() = 0;
+ virtual IEdgeLabel *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IChildNode
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IChildNode)
+ enum NodeRelation { PublicInheritance, ProtectedInheritance,
+ PrivateInheritance, Usage, TemplateInstance
+ };
+ virtual INode * node() const = 0;
+ virtual NodeRelation relation() const = 0;
+ virtual const IString * relationString() const = 0;
+ virtual IEdgeLabelIterator *edgeLabels() const = 0;
+};
+
+class IChildNodeIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IChildNodeIterator)
+ virtual IChildNode *toFirst() = 0;
+ virtual IChildNode *toLast() = 0;
+ virtual IChildNode *toNext() = 0;
+ virtual IChildNode *toPrev() = 0;
+ virtual IChildNode *current() const = 0;
+ virtual void release() = 0;
+};
+
+class INode
+{
+ public:
+ VIRTUAL_DESTRUCTOR(INode)
+ virtual const IString * id() const = 0;
+ virtual const IString * label() const = 0;
+ virtual const IString * linkId() const = 0;
+ virtual IChildNodeIterator *children() const = 0;
+};
+
+class INodeIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(INodeIterator)
+ virtual INode *toFirst() = 0;
+ virtual INode *toLast() = 0;
+ virtual INode *toNext() = 0;
+ virtual INode *toPrev() = 0;
+ virtual INode *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IGraph
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IGraph)
+ virtual INodeIterator *nodes() const = 0;
+};
+
+class IMember
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IMember)
+ enum MemberKind { Invalid=0,
+ Define, Property, Variable, Typedef, Enum,
+ Function, Signal, Prototype, Friend, DCOP, Slot,
+ EnumValue
+ };
+ virtual ICompound *compound() const = 0;
+ virtual ISection *section() const = 0;
+ virtual MemberKind kind() const = 0;
+ virtual const IString * kindString() const = 0;
+ virtual const IString * id() const = 0;
+ virtual const IString * protection() const = 0;
+ virtual const IString * virtualness() const = 0;
+ virtual ILinkedTextIterator *type() const = 0;
+ virtual const IString * typeString() const = 0;
+ virtual const IString * name() const = 0;
+ virtual const IString * readAccessor() const = 0;
+ virtual const IString * writeAccessor() const = 0;
+ virtual const IString * definition() const = 0;
+ virtual const IString * argsstring() const = 0;
+ virtual bool isConst() const = 0;
+ virtual bool isVolatile() const = 0;
+ virtual bool isStatic() const = 0;
+ virtual bool isExplicit() const = 0;
+ virtual bool isInline() const = 0;
+ virtual bool isMutable() const = 0;
+ virtual bool isReadable() const = 0;
+ virtual bool isWritable() const = 0;
+ virtual IParamIterator *parameters() const = 0;
+ virtual IParamIterator *templateParameters() const = 0;
+ virtual ILinkedTextIterator *initializer() const = 0;
+ virtual ILinkedTextIterator *exceptions() const = 0;
+ virtual IMemberReferenceIterator *references() const = 0;
+ virtual IMemberReferenceIterator *referencedBy() const = 0;
+ virtual const IString *bodyFile() const = 0;
+ virtual int bodyStart() const = 0;
+ virtual int bodyEnd() const = 0;
+ virtual const IString * definitionFile() const = 0;
+ virtual int definitionLine() const = 0;
+ virtual IMemberReference *reimplements() const = 0;
+ virtual IMemberReferenceIterator *reimplementedBy() const = 0;
+ virtual IDocRoot *briefDescription() const = 0;
+ virtual IDocRoot *detailedDescription() const = 0;
+ virtual IDocRoot *inbodyDescription() const = 0;
+};
+
+class IDefine : public IMember
+{
+ public:
+};
+
+class IProperty : public IMember
+{
+ public:
+};
+
+class IVariable : public IMember
+{
+ public:
+};
+
+class ITypedef : public IMember
+{
+ public:
+};
+
+class IFunction : public IMember
+{
+ public:
+};
+
+class ISignal : public IMember
+{
+ public:
+};
+
+class IPrototype : public IMember
+{
+ public:
+};
+
+class IFriend : public IMember
+{
+ public:
+};
+
+class IDCOP : public IMember
+{
+ public:
+};
+
+class ISlot : public IMember
+{
+ public:
+};
+
+class IEnumValue : public IMember
+{
+ public:
+ virtual const IString * name() const = 0;
+};
+
+/*! \brief Include relation
+ */
+class IInclude
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IInclude)
+ virtual const IString * name() const = 0;
+ virtual const IString * refId() const = 0;
+ virtual bool isLocal() const = 0;
+};
+
+class IIncludeIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IIncludeIterator)
+ virtual IInclude *toFirst() = 0;
+ virtual IInclude *toLast() = 0;
+ virtual IInclude *toNext() = 0;
+ virtual IInclude *toPrev() = 0;
+ virtual IInclude *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IMemberIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IMemberIterator)
+ virtual IMember *toFirst() = 0;
+ virtual IMember *toLast() = 0;
+ virtual IMember *toNext() = 0;
+ virtual IMember *toPrev() = 0;
+ virtual IMember *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IEnum : public IMember
+{
+ public:
+ virtual IMemberIterator *enumValues() const = 0;
+};
+
+/*! \brief The interface to a section in the object model.
+ *
+ * A compound can have a number of sections, where each
+ * section contains a set of members with the properties implied by
+ * the section kind. The kind() method returns the kind of the section.
+ * The members of the section can be accessed via members(). Apart
+ * from using kind(), some of the individual properties of the section can
+ * also be inspected via isStatic(), isPublic(), isProtected() and
+ * isPrivate().
+ */
+class ISection
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ISection)
+ /*! Possible section types */
+ enum SectionKind
+ { Invalid=0,
+ UserDefined, //!< A user defined member group
+ PubTypes, //!< Public member typedefs
+ PubFuncs, //!< Public member functions
+ PubAttribs, //!< Public member attributes
+ PubSlots, //!< Public Qt Slots
+ Signals, //!< Qt Signals
+ DCOPFuncs, //!< KDE-DCOP interface functions
+ Properties, //!< IDL properties
+ Events, //!< C# events
+ PubStatFuncs, //!< Public static member functions
+ PubStatAttribs, //!< Public static attributes
+ ProTypes, //!< Protected member typedefs
+ ProFuncs, //!< Protected member functions
+ ProAttribs, //!< Protected member attributes
+ ProSlots, //!< Protected slots
+ ProStatFuncs, //!< Protected static member functions
+ ProStatAttribs, //!< Protected static member attributes
+ PacTypes, //!< Package member typedefs
+ PacFuncs, //!< Package member functions
+ PacAttribs, //!< Package member attributes
+ PacStatFuncs, //!< Package static member functions
+ PacStatAttribs, //!< Package static member attributes
+ PriTypes, //!< Private member typedefs
+ PriFuncs, //!< Private member functions
+ PriAttribs, //!< Private member attributes
+ PriSlots, //!< Private Qt slots
+ PriStatFuncs, //!< Private static member functions
+ PriStatAttribs, //!< Private static member attributes
+ Friend, //!< Friends
+ Related, //!< Function marked as related
+ Defines, //!< Preprocessor defines
+ Prototypes, //!< Global function prototypes
+ Typedefs, //!< Global typedefs
+ Enums, //!< Enumerations
+ Functions, //!< Global functions
+ Variables //!< Global variables
+ };
+
+ /*! Returns a string representation of the value returned by kind() */
+ virtual const IString * kindString() const = 0;
+
+ /*! Returns what kind of section this is */
+ virtual SectionKind kind() const = 0;
+
+ /*! Returns the description attached to this section (for user defined
+ * sections, also known as member groups).
+ */
+ virtual IDocRoot *description() const = 0;
+
+ /*! Returns an iterator for the members of this section */
+ virtual IMemberIterator *members() const = 0;
+
+ /*! Returns \c true if this section contains statics */
+ virtual bool isStatic() const = 0;
+
+ /*! Returns \c true if this section belongs to a
+ * public section of a class
+ */
+ virtual bool isPublic() const = 0;
+
+ /*! Returns \c true if this section belongs to a
+ * private section of a class
+ */
+ virtual bool isPrivate() const = 0;
+
+ /*! Returns \c true if this section belongs to a
+ * protected section of a class
+ * */
+ virtual bool isProtected() const = 0;
+};
+
+class IUserDefined : public ISection
+{
+ public:
+ virtual const IString * header() const = 0;
+};
+
+class ISectionIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ISectionIterator)
+ virtual ISection *toFirst() = 0;
+ virtual ISection *toLast() = 0;
+ virtual ISection *toNext() = 0;
+ virtual ISection *toPrev() = 0;
+ virtual ISection *current() const = 0;
+ virtual void release() = 0;
+};
+
+/*! \brief The interface to a compound in the object model.
+ *
+ * A compound has a name which can be obtained via the name() method
+ * and a unique id, which is return via the id() method.
+ * A compound consists zero or more members which are grouped into sections.
+ * The sections() method can be used to access the individual sections.
+ * Alternatively, members can be obtained by name or id. There are
+ * different types of compounds. The kind() method returns what kind of
+ * compound this is. Depending on the return value one can dynamically
+ * cast an interface pointer to an more specialised interface that provides
+ * additional methods.
+ * Example:
+ * \code
+ * ICompound *comp=...;
+ * if (comp->kind()==ICompound::Class)
+ * {
+ * IClass *cls = dynamic_cast<IClass*>(comp);
+ * // use methods of IClass
+ * }
+ * \endcode
+ * The documentation that is provided by a compound is available via
+ * the briefDescription() and detailedDescription() methods.
+ * To avoid excessive memory usage, release() should be called (once) on each
+ * compound interface pointer that is no longer needed.
+ */
+class ICompound
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ICompound)
+ /*! Represents the kind of compounds recognised by doxygen. */
+ enum CompoundKind { Invalid=0,
+ Class, Struct, Union, Interface, Protocol, Category,
+ Exception, File, Namespace, Group, Page, Example, Dir
+ };
+
+ /*! Returns the name of this compound */
+ virtual const IString * name() const = 0;
+
+ /*! Returns the id of this compound. The id is a
+ * unique string representing a specific compound object.
+ */
+ virtual const IString * id() const = 0;
+
+ /*! Returns the kind of compound. See #CompoundKind for possible
+ * values.
+ */
+ virtual CompoundKind kind() const = 0;
+
+ /*! Returns a string representation of the compound kind.
+ * @see kind()
+ */
+ virtual const IString * kindString() const = 0;
+
+ /*! Returns an iterator for the different member sections in this
+ * compound.
+ */
+ virtual ISectionIterator *sections() const = 0;
+
+ /*! Returns a tree-structured representation of the brief
+ * description that is attached to this compound.
+ */
+ virtual IDocRoot *briefDescription() const = 0;
+
+ /*! Returns a tree-structured representation of the detailed
+ * description that is attached to this compound.
+ */
+ virtual IDocRoot *detailedDescription() const = 0;
+
+ /*! Returns an interface to a member given its id.
+ * @param id The member id.
+ */
+ virtual IMember *memberById(const char * id) const = 0;
+
+ /*! Returns a list of all members within the compound having a certain
+ * name. Member overloading is the reason why there can be more than
+ * one member.
+ * @param name The name of the member.
+ */
+ virtual IMemberIterator *memberByName(const char * name) const = 0;
+
+ /*! Decreases the reference counter for this compound. If it reaches
+ * zero, the memory for the compound will be released.
+ */
+ virtual void release() = 0;
+};
+
+class ICompoundIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(ICompoundIterator)
+ virtual void toFirst() = 0;
+ virtual void toLast() = 0;
+ virtual void toNext() = 0;
+ virtual void toPrev() = 0;
+ virtual ICompound *current() const = 0;
+ virtual void release() = 0;
+};
+
+class IRelatedCompound
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IRelatedCompound)
+ enum Protection { Public, Protected, Private };
+ enum Kind { Normal, Virtual };
+ virtual ICompound *compound() const = 0;
+ virtual Protection protection() const = 0;
+ virtual Kind kind() const = 0;
+ virtual const IString *name() const = 0;
+
+};
+
+class IRelatedCompoundIterator
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IRelatedCompoundIterator)
+ virtual IRelatedCompound *toFirst() = 0;
+ virtual IRelatedCompound *toLast() = 0;
+ virtual IRelatedCompound *toNext() = 0;
+ virtual IRelatedCompound *toPrev() = 0;
+ virtual IRelatedCompound *current() const = 0;
+ virtual void release() = 0;
+};
+
+/*! \brief The interface to a class in the object model.
+ */
+class IClass : public ICompound
+{
+ public:
+ virtual IGraph *inheritanceGraph() const = 0;
+ virtual IGraph *collaborationGraph() const = 0;
+ virtual IRelatedCompoundIterator *baseCompounds() const = 0;
+ virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+ virtual IParamIterator *templateParameters() const = 0;
+ virtual const IString *locationFile() const = 0;
+ virtual int locationLine() const = 0;
+ virtual const IString *locationBodyFile() const = 0;
+ virtual int locationBodyStartLine() const = 0;
+ virtual int locationBodyEndLine() const = 0;
+
+ // TODO:
+ // class:
+ // listOfAllMembers()
+ // protection()
+ // isAbstract()
+};
+
+/*! \brief The interface to a struct in the object model.
+ */
+class IStruct : public ICompound
+{
+ public:
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+ virtual IRelatedCompoundIterator *baseCompounds() const = 0;
+ virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
+ virtual const IString *locationFile() const = 0;
+ virtual int locationLine() const = 0;
+ virtual int locationBodyStartLine() const = 0;
+ virtual int locationBodyEndLine() const = 0;
+};
+
+/*! \brief The interface to a union in the object model.
+ */
+class IUnion : public ICompound
+{
+ public:
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+};
+
+/*! \brief The interface to a Java/IDL interface in the object model.
+ */
+class IInterface : public ICompound
+{
+ public:
+ virtual IRelatedCompoundIterator *baseCompounds() const = 0;
+ virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
+};
+
+
+/*! \brief The interface to a Java/IDL exception in the object model.
+ */
+class IException : public ICompound
+{
+};
+
+/*! \brief The interface to a namespace in the object model.
+ */
+class INamespace : public ICompound
+{
+ public:
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+};
+
+/*! \brief The interface to a file in the object model.
+ */
+class IFile : public ICompound
+{
+ public:
+ virtual IGraph *includeDependencyGraph() const = 0;
+ virtual IGraph *includedByDependencyGraph() const = 0;
+ virtual IDocProgramListing *source() const = 0;
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+
+ virtual IIncludeIterator *includes() const = 0;
+ virtual IIncludeIterator *includedBy() const = 0;
+
+ // ICompound *innerNamespaces()
+ // ICompoundIterator *innerClasses()
+};
+
+/*! \brief The interface to a group in the object model.
+ */
+class IGroup : public ICompound
+{
+ public:
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+ // group:
+ // Title()
+ // innerFile()
+ // innerPage()
+};
+
+/*! \brief The interface to a page in the object model.
+ */
+class IPage : public ICompound
+{
+ public:
+ virtual const IDocTitle *title() const = 0;
+};
+
+/** \brief Interface to a directory in the object model. */
+class IDir : public ICompound
+{
+ public:
+ virtual ICompoundIterator *nestedCompounds() const = 0;
+};
+
+/*! Root node of the object model. */
+class IDoxygen
+{
+ public:
+ VIRTUAL_DESTRUCTOR(IDoxygen)
+
+ /*! Returns an iterator that can be used to iterate over the list
+ * of compounds found in the project.
+ */
+ virtual ICompoundIterator *compounds() const = 0;
+
+ /*! Returns a compound given its unique \a id. If you have a
+ * compound id this function is much more efficient than iterating
+ * over the compound list. Returns 0 if the id is not valid.
+ */
+ virtual ICompound *compoundById(const char * id) const = 0;
+
+ /*! Returns a compound given its name (including the scope).
+ * Returns 0 if the name is not found in the project.
+ */
+ virtual ICompound *compoundByName(const char * name) const = 0;
+
+ /*! Returns an interface to a compound containing a member given it the
+ * member's id. Given the ICompound interface one can use the same id
+ * to obtain the IMember interface.
+ * @param id The member id.
+ */
+ virtual ICompound *memberById(const char * id) const = 0;
+
+ /*! Returns a list of all compounds containing at least one members
+ * with a certain name. Each compound can be asked to return the
+ * list of members with that name.
+ * @param name The name of the member.
+ */
+ virtual ICompoundIterator *memberByName(const char * name) const = 0;
+
+ /*! Releases the memory for the object hierarchy obtained by
+ * createdObjecModelFromXML(). First release all iterators before calling
+ * this function.
+ */
+ virtual void release() = 0;
+
+ /*! Sets the debug level.
+ * - 0 all debugging messages are disabled (the default).
+ * - 1 display important messages only
+ * - 2 display any messages.
+ */
+ virtual void setDebugLevel(int level) = 0;
+
+ /*! Reads an XML directory produced by doxygen and builds up a data
+ * structure representing the contents of the XML files in the directory.
+ */
+ virtual bool readXMLDir(const char *xmlDirName) = 0;
+};
+
+/*! Factory method that creates an empty object model for a doxygen generated XML file.
+ * Use the readXMLDir() method to build the model from an XML output
+ * directory containing doxygen output.
+ */
+IDoxygen *createObjectModel();
+
+#endif
diff --git a/addon/doxmlparser/src/CMakeLists.txt b/addon/doxmlparser/src/CMakeLists.txt
new file mode 100644
index 0000000..35f6c83
--- /dev/null
+++ b/addon/doxmlparser/src/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(
+ .
+ ../include
+ ${CMAKE_SOURCE_DIR}/qtools
+)
+add_library(doxmlparser STATIC
+ basehandler.cpp
+ compoundhandler.cpp
+ debug.cpp
+ dochandler.cpp
+ graphhandler.cpp
+ linkedtexthandler.cpp
+ loamhandler.cpp
+ mainhandler.cpp
+ memberhandler.cpp
+ paramhandler.cpp
+ sectionhandler.cpp
+)
diff --git a/addon/doxmlparser/src/compoundhandler.cpp b/addon/doxmlparser/src/compoundhandler.cpp
index 3e729e9..0f51792 100644
--- a/addon/doxmlparser/src/compoundhandler.cpp
+++ b/addon/doxmlparser/src/compoundhandler.cpp
@@ -22,6 +22,7 @@
#include "paramhandler.h"
#include "loamhandler.h"
#include "memberhandler.h"
+#include "linkedtexthandler.h"
//----------------------------------------------------------------------------
diff --git a/addon/doxmlparser/src/compoundhandler.h b/addon/doxmlparser/src/compoundhandler.h
index f669133..b05ba3d 100644
--- a/addon/doxmlparser/src/compoundhandler.h
+++ b/addon/doxmlparser/src/compoundhandler.h
@@ -51,7 +51,7 @@ class IncludeHandler : public IInclude, public BaseHandler<IncludeHandler>
virtual const IString * refId() const
{ return &m_refId; }
virtual bool isLocal() const
- { return &m_isLocal; }
+ { return m_isLocal; }
private:
IBaseHandler *m_parent;
diff --git a/addon/doxmlparser/src/doxmlintf.h b/addon/doxmlparser/src/doxmlintf.h
deleted file mode 100644
index 22cecdb..0000000
--- a/addon/doxmlparser/src/doxmlintf.h
+++ /dev/null
@@ -1,1141 +0,0 @@
-/******************************************************************************
- *
- * $Id$
- *
- *
- * Copyright (C) 1997-2015 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.
- *
- */
-
-#ifndef _DOXMLINTF_H
-#define _DOXMLINTF_H
-
-/*! \file
- * \brief The interface to the object model provided by the XML parser
- * library.
- *
- * To start using this library one calls createObjectModel() and then
- * uses the returned IDoxygen interface to read doxygen generated
- * XML output and navigate through the information contained in it.
- *
- * @see createObjectModel()
- */
-
-class IMember;
-class IDocIterator;
-class ICompound;
-class ISection;
-class INode;
-class IDocInternal;
-class IDocRoot;
-
-#define VIRTUAL_DESTRUCTOR(x) virtual ~x() {}
-
-/*! \brief Read only interface to a string.
- */
-class IString
-{
- public:
- VIRTUAL_DESTRUCTOR(IString)
- /*! Returns a latin1 character representation of the string. */
- virtual const char *latin1() const = 0;
- /*! Returns a utf8 character representation of the string. */
- virtual const char *utf8() const = 0;
- /*! Returns a 16-bit unicode character representation of the character at
- * position \a index in the string. The first character is at index 0.
- */
- virtual unsigned short unicodeCharAt(int index) const = 0;
- /*! Returns true if this string is empty or false otherwise */
- virtual bool isEmpty() const = 0;
- /*! Returns the number of characters in the string. */
- virtual int length() const = 0;
-};
-
-/*! \brief Base interface for hyperlinked text
- *
- * Depending on the result of kind() the interface is extended by
- * ILT_Text or ILT_Ref.
- */
-class ILinkedText
-{
- public:
- VIRTUAL_DESTRUCTOR(ILinkedText)
- enum Kind { Kind_Text, Kind_Ref };
- virtual Kind kind() const = 0;
-};
-
-/*! \brief Plain text fragment.
- */
-class ILT_Text : public ILinkedText
-{
- public:
- VIRTUAL_DESTRUCTOR(ILT_Text)
- virtual const IString *text() const = 0;
-};
-
-/*! \brief Reference to an object.
- */
-class ILT_Ref : public ILinkedText
-{
- public:
- VIRTUAL_DESTRUCTOR(ILT_Ref)
- enum TargetKind { Member, Compound };
- virtual const IString *id() const = 0;
- virtual TargetKind targetKind() const = 0;
- virtual const IString *external() const = 0;
- virtual const IString *text() const = 0;
-};
-
-/*! \brief Iterates over a list of ILinkedText fragments.
- */
-class ILinkedTextIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(ILinkedTextIterator)
- virtual ILinkedText *toFirst() = 0;
- virtual ILinkedText *toLast() = 0;
- virtual ILinkedText *toNext() = 0;
- virtual ILinkedText *toPrev() = 0;
- virtual ILinkedText *current() const = 0;
- virtual void release() = 0;
-};
-
-/*! \brief Representation of a parameter of a function. */
-class IParam
-{
- public:
- VIRTUAL_DESTRUCTOR(IParam)
- virtual ILinkedTextIterator *type() const = 0;
- virtual const IString * declarationName() const = 0;
- virtual const IString * definitionName() const = 0;
- virtual const IString * attrib() const = 0;
- virtual const IString * arraySpecifier() const = 0;
- virtual ILinkedTextIterator *defaultValue() const = 0;
- virtual IDocRoot *briefDescription() const = 0;
-};
-
-class IParamIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IParamIterator)
- virtual IParam *toFirst() = 0;
- virtual IParam *toLast() = 0;
- virtual IParam *toNext() = 0;
- virtual IParam *toPrev() = 0;
- virtual IParam *current() const = 0;
- virtual void release() = 0;
-};
-
-class IMemberReference
-{
- public:
- VIRTUAL_DESTRUCTOR(IMemberReference)
- virtual IMember *member() const = 0;
- virtual const IString * name() const = 0;
- virtual const IString * scope() const = 0;
- virtual const IString * protection() const = 0;
- virtual const IString * virtualness() const = 0;
- virtual const IString * ambiguityScope() const = 0;
-};
-
-class IMemberReferenceIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IMemberReferenceIterator)
- virtual IMemberReference *toFirst() = 0;
- virtual IMemberReference *toLast() = 0;
- virtual IMemberReference *toNext() = 0;
- virtual IMemberReference *toPrev() = 0;
- virtual IMemberReference *current() const = 0;
- virtual void release() = 0;
-};
-
-class IDoc
-{
- public:
- VIRTUAL_DESTRUCTOR(IDoc)
- enum Kind
- {
- Invalid = 0, // 0
- Para, // 1 -> IDocPara
- Text, // 2 -> IDocText
- MarkupModifier, // 3 -> IDocMarkupModifier
- ItemizedList, // 4 -> IDocItemizedList
- OrderedList, // 5 -> IDocOrderedList
- ListItem, // 6 -> IDocListItem
- ParameterList, // 7 -> IDocParameterList
- Parameter, // 8 -> IDocParameter
- SimpleSect, // 9 -> IDocSimpleSect
- Title, // 10 -> IDocTitle
- Ref, // 11 -> IDocRef
- VariableList, // 12 -> IDocVariableList
- VariableListEntry, // 13 -> IDocVariableListEntry
- HRuler, // 14 -> IDocHRuler
- LineBreak, // 15 -> IDocLineBreak
- ULink, // 16 -> IDocULink
- EMail, // 17 -> IDocEMail
- Link, // 18 -> IDocLink
- ProgramListing, // 19 -> IDocProgramListing
- CodeLine, // 20 -> IDocCodeLine
- Highlight, // 21 -> IDocHighlight
- Formula, // 22 -> IDocFormula
- Image, // 23 -> IDocImage
- DotFile, // 24 -> IDocDotFile
- IndexEntry, // 25 -> IDocIndexEntry
- Table, // 26 -> IDocTable
- Row, // 27 -> IDocRow
- Entry, // 28 -> IDocEntry
- Section, // 29 -> IDocSection
- Verbatim, // 30 -> IDocVerbatim
- Copy, // 31 -> IDocCopy
- TocList, // 32 -> IDocTocList
- TocItem, // 33 -> IDocTocItem
- Anchor, // 34 -> IDocAnchor
- Symbol, // 35 -> IDocSymbol
- Internal, // 36 -> IDocInternal
- Root, // 37 -> IDocRoot
- ParameterItem // 38 -> IDocParameterItem
- };
- virtual Kind kind() const = 0;
-};
-
-class IDocMarkup : public IDoc
-{
- public:
- enum Markup
- {
- Normal = 0x000,
- Bold = 0x001,
- Emphasis = 0x002,
- ComputerOutput = 0x004,
- Subscript = 0x008,
- Superscript = 0x010,
- SmallFont = 0x020,
- Center = 0x040,
- Preformatted = 0x080,
- Heading = 0x100
- };
-};
-
-class IDocPara : public IDoc
-{
- public:
- virtual IDocIterator *contents() const = 0;
-};
-
-class IDocText : public IDocMarkup
-{
- public:
- virtual const IString * text() const = 0;
- virtual int markup() const = 0;
- virtual int headingLevel() const = 0;
-};
-
-class IDocMarkupModifier : public IDoc
-{
- public:
- virtual bool enabled() const = 0;
- virtual int markup() const = 0;
- virtual int headingLevel() const = 0;
-};
-
-class IDocItemizedList : public IDoc
-{
- public:
- virtual IDocIterator *elements() const = 0;
-};
-
-class IDocOrderedList : public IDoc
-{
- public:
- virtual IDocIterator *elements() const = 0;
-};
-
-class IDocListItem : public IDoc
-{
- public:
- virtual IDocIterator *contents() const = 0;
-};
-
-class IDocParameterList : public IDoc
-{
- public:
- enum Types { Param, RetVal, Exception };
- virtual Types sectType() const = 0;
- virtual IDocIterator *params() const = 0;
-};
-
-class IDocParameterItem : public IDoc
-{
- public:
- virtual IDocIterator *paramNames() const = 0;
- virtual IDocPara *description() const = 0;
-};
-
-class IDocParameter : public IDoc
-{
- public:
- virtual const IString * name() const = 0;
-};
-
-class IDocTitle : public IDoc
-{
- public:
- virtual IDocIterator *title() const = 0;
-};
-
-class IDocSimpleSect : public IDoc
-{
- public:
- enum Types { Invalid = 0,
- See, Return, Author, Version,
- Since, Date, Bug, Note,
- Warning, Par, Deprecated, Pre,
- Post, Invar, Remark, Attention,
- Todo, Test, RCS, EnumValues,
- Examples
- };
- virtual Types type() const = 0;
- virtual const IString * typeString() const = 0;
- virtual IDocTitle *title() const = 0;
- virtual IDocPara *description() const = 0;
-};
-
-class IDocRef : public IDoc
-{
- public:
- enum TargetKind { Member, Compound };
- virtual const IString * refId() const = 0;
- virtual TargetKind targetKind() const = 0;
- virtual const IString * external() const = 0;
- virtual const IString * text() const = 0;
-};
-
-class IDocVariableList : public IDoc
-{
- public:
- virtual IDocIterator *entries() const = 0;
-};
-
-class IDocVariableListEntry : public IDoc
-{
- public:
- virtual ILinkedTextIterator * term() const = 0;
- virtual IDocPara *description() const = 0;
-};
-
-class IDocHRuler : public IDoc
-{
-};
-
-class IDocLineBreak : public IDoc
-{
-};
-
-class IDocULink : public IDoc
-{
- public:
- virtual const IString * url() const = 0;
- virtual const IString * text() const = 0;
-};
-
-class IDocEMail : public IDoc
-{
- public:
- virtual const IString * address() const = 0;
-};
-
-class IDocLink : public IDoc
-{
- public:
- virtual const IString * refId() const = 0;
- virtual const IString * text() const = 0;
-};
-
-class IDocProgramListing : public IDoc
-{
- public:
- virtual IDocIterator *codeLines() const = 0;
-};
-
-class IDocCodeLine : public IDoc
-{
- public:
- virtual int lineNumber() const = 0;
- virtual const IString * refId() const = 0;
- virtual IDocIterator *codeElements() const = 0;
-};
-
-class IDocHighlight : public IDoc
-{
- public:
- enum HighlightKind
- { Invalid=0,
- Comment, Keyword,
- KeywordType, KeywordFlow, CharLiteral,
- StringLiteral, Preprocessor
- };
- virtual HighlightKind highlightKind() const = 0;
- virtual IDocIterator *codeElements() const = 0;
-};
-
-class IDocFormula : public IDoc
-{
- public:
- virtual const IString * id() const = 0;
- virtual const IString * text() const = 0;
-};
-
-class IDocImage : public IDoc
-{
- public:
- virtual const IString * name() const = 0;
- virtual const IString * caption() const = 0;
-};
-
-class IDocDotFile : public IDoc
-{
- public:
- virtual const IString * name() const = 0;
- virtual const IString * caption() const = 0;
-};
-
-class IDocIndexEntry : public IDoc
-{
- public:
- virtual const IString * primary() const = 0;
- virtual const IString * secondary() const = 0;
-};
-
-class IDocTable : public IDoc
-{
- public:
- virtual IDocIterator *rows() const = 0;
- virtual int numColumns() const = 0;
- virtual const IString * caption() const = 0;
-};
-
-class IDocRow : public IDoc
-{
- public:
- virtual IDocIterator *entries() const = 0;
-};
-
-class IDocEntry : public IDoc
-{
- public:
- virtual IDocIterator *contents() const = 0;
-};
-
-class IDocSection : public IDoc
-{
- public:
- virtual const IString * id() const = 0;
- virtual int level() const = 0;
- virtual IDocTitle *title() const = 0;
- virtual IDocIterator *paragraphs() const = 0;
- virtual IDocIterator *subSections() const = 0;
- virtual IDocInternal *internal() const = 0;
-};
-
-class IDocInternal : public IDoc
-{
- public:
- virtual IDocIterator *paragraphs() const = 0;
- virtual IDocIterator *subSections() const = 0;
-};
-
-class IDocTocList : public IDoc
-{
- public:
- virtual IDocIterator *elements() const = 0;
-};
-
-class IDocTocItem : public IDoc
-{
- public:
- virtual const IString *id() const = 0;
- virtual const IString *title() const = 0;
-};
-
-class IDocCopy : public IDoc
-{
- public:
- virtual IDocIterator *contents() const = 0;
-};
-
-class IDocVerbatim : public IDoc
-{
- public:
- enum Types { Invalid = 0, HtmlOnly, LatexOnly, Verbatim };
- virtual const IString *text() const = 0;
- virtual Types type() const = 0;
-};
-
-class IDocAnchor : public IDoc
-{
- public:
- virtual const IString *id() const = 0;
-};
-
-class IDocSymbol : public IDoc
-{
- public:
- enum Types
- { Invalid = 0,
- Umlaut, Acute, Grave, Circ, Tilde, Szlig, Cedil, Ring, Nbsp, Copy
- };
- virtual Types type() const = 0;
- virtual const IString * typeString() const = 0;
- virtual char letter() const = 0;
-};
-
-class IDocRoot : public IDoc
-{
- public:
- virtual IDocIterator *contents() const = 0;
- virtual IDocInternal *internal() const = 0;
-};
-
-class IDocIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IDocIterator)
- virtual IDoc *toFirst() = 0;
- virtual IDoc *toLast() = 0;
- virtual IDoc *toNext() = 0;
- virtual IDoc *toPrev() = 0;
- virtual IDoc *current() const = 0;
- virtual void release() = 0;
-};
-
-class IEdgeLabel
-{
- public:
- VIRTUAL_DESTRUCTOR(IEdgeLabel)
- virtual const IString * label() const = 0;
-};
-
-class IEdgeLabelIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IEdgeLabelIterator)
- virtual IEdgeLabel *toFirst() = 0;
- virtual IEdgeLabel *toLast() = 0;
- virtual IEdgeLabel *toNext() = 0;
- virtual IEdgeLabel *toPrev() = 0;
- virtual IEdgeLabel *current() const = 0;
- virtual void release() = 0;
-};
-
-class IChildNode
-{
- public:
- VIRTUAL_DESTRUCTOR(IChildNode)
- enum NodeRelation { PublicInheritance, ProtectedInheritance,
- PrivateInheritance, Usage, TemplateInstance
- };
- virtual INode * node() const = 0;
- virtual NodeRelation relation() const = 0;
- virtual const IString * relationString() const = 0;
- virtual IEdgeLabelIterator *edgeLabels() const = 0;
-};
-
-class IChildNodeIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IChildNodeIterator)
- virtual IChildNode *toFirst() = 0;
- virtual IChildNode *toLast() = 0;
- virtual IChildNode *toNext() = 0;
- virtual IChildNode *toPrev() = 0;
- virtual IChildNode *current() const = 0;
- virtual void release() = 0;
-};
-
-class INode
-{
- public:
- VIRTUAL_DESTRUCTOR(INode)
- virtual const IString * id() const = 0;
- virtual const IString * label() const = 0;
- virtual const IString * linkId() const = 0;
- virtual IChildNodeIterator *children() const = 0;
-};
-
-class INodeIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(INodeIterator)
- virtual INode *toFirst() = 0;
- virtual INode *toLast() = 0;
- virtual INode *toNext() = 0;
- virtual INode *toPrev() = 0;
- virtual INode *current() const = 0;
- virtual void release() = 0;
-};
-
-class IGraph
-{
- public:
- VIRTUAL_DESTRUCTOR(IGraph)
- virtual INodeIterator *nodes() const = 0;
-};
-
-class IMember
-{
- public:
- VIRTUAL_DESTRUCTOR(IMember)
- enum MemberKind { Invalid=0,
- Define, Property, Variable, Typedef, Enum,
- Function, Signal, Prototype, Friend, DCOP, Slot,
- EnumValue
- };
- virtual ICompound *compound() const = 0;
- virtual ISection *section() const = 0;
- virtual MemberKind kind() const = 0;
- virtual const IString * kindString() const = 0;
- virtual const IString * id() const = 0;
- virtual const IString * protection() const = 0;
- virtual const IString * virtualness() const = 0;
- virtual ILinkedTextIterator *type() const = 0;
- virtual const IString * typeString() const = 0;
- virtual const IString * name() const = 0;
- virtual const IString * readAccessor() const = 0;
- virtual const IString * writeAccessor() const = 0;
- virtual const IString * definition() const = 0;
- virtual const IString * argsstring() const = 0;
- virtual bool isConst() const = 0;
- virtual bool isVolatile() const = 0;
- virtual bool isStatic() const = 0;
- virtual bool isExplicit() const = 0;
- virtual bool isInline() const = 0;
- virtual bool isMutable() const = 0;
- virtual bool isReadable() const = 0;
- virtual bool isWritable() const = 0;
- virtual IParamIterator *parameters() const = 0;
- virtual IParamIterator *templateParameters() const = 0;
- virtual ILinkedTextIterator *initializer() const = 0;
- virtual ILinkedTextIterator *exceptions() const = 0;
- virtual IMemberReferenceIterator *references() const = 0;
- virtual IMemberReferenceIterator *referencedBy() const = 0;
- virtual const IString *bodyFile() const = 0;
- virtual int bodyStart() const = 0;
- virtual int bodyEnd() const = 0;
- virtual const IString * definitionFile() const = 0;
- virtual int definitionLine() const = 0;
- virtual IMemberReference *reimplements() const = 0;
- virtual IMemberReferenceIterator *reimplementedBy() const = 0;
- virtual IDocRoot *briefDescription() const = 0;
- virtual IDocRoot *detailedDescription() const = 0;
- virtual IDocRoot *inbodyDescription() const = 0;
-};
-
-class IDefine : public IMember
-{
- public:
-};
-
-class IProperty : public IMember
-{
- public:
-};
-
-class IVariable : public IMember
-{
- public:
-};
-
-class ITypedef : public IMember
-{
- public:
-};
-
-class IFunction : public IMember
-{
- public:
-};
-
-class ISignal : public IMember
-{
- public:
-};
-
-class IPrototype : public IMember
-{
- public:
-};
-
-class IFriend : public IMember
-{
- public:
-};
-
-class IDCOP : public IMember
-{
- public:
-};
-
-class ISlot : public IMember
-{
- public:
-};
-
-class IEnumValue : public IMember
-{
- public:
- virtual const IString * name() const = 0;
-};
-
-/*! \brief Include relation
- */
-class IInclude
-{
- public:
- VIRTUAL_DESTRUCTOR(IInclude)
- virtual const IString * name() const = 0;
- virtual const IString * refId() const = 0;
- virtual bool isLocal() const = 0;
-};
-
-class IIncludeIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IIncludeIterator)
- virtual IInclude *toFirst() = 0;
- virtual IInclude *toLast() = 0;
- virtual IInclude *toNext() = 0;
- virtual IInclude *toPrev() = 0;
- virtual IInclude *current() const = 0;
- virtual void release() = 0;
-};
-
-class IMemberIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IMemberIterator)
- virtual IMember *toFirst() = 0;
- virtual IMember *toLast() = 0;
- virtual IMember *toNext() = 0;
- virtual IMember *toPrev() = 0;
- virtual IMember *current() const = 0;
- virtual void release() = 0;
-};
-
-class IEnum : public IMember
-{
- public:
- virtual IMemberIterator *enumValues() const = 0;
-};
-
-/*! \brief The interface to a section in the object model.
- *
- * A compound can have a number of sections, where each
- * section contains a set of members with the properties implied by
- * the section kind. The kind() method returns the kind of the section.
- * The members of the section can be accessed via members(). Apart
- * from using kind(), some of the individual properties of the section can
- * also be inspected via isStatic(), isPublic(), isProtected() and
- * isPrivate().
- */
-class ISection
-{
- public:
- VIRTUAL_DESTRUCTOR(ISection)
- /*! Possible section types */
- enum SectionKind
- { Invalid=0,
- UserDefined, //!< A user defined member group
- PubTypes, //!< Public member typedefs
- PubFuncs, //!< Public member functions
- PubAttribs, //!< Public member attributes
- PubSlots, //!< Public Qt Slots
- Signals, //!< Qt Signals
- DCOPFuncs, //!< KDE-DCOP interface functions
- Properties, //!< IDL properties
- Events, //!< C# events
- PubStatFuncs, //!< Public static member functions
- PubStatAttribs, //!< Public static attributes
- ProTypes, //!< Protected member typedefs
- ProFuncs, //!< Protected member functions
- ProAttribs, //!< Protected member attributes
- ProSlots, //!< Protected slots
- ProStatFuncs, //!< Protected static member functions
- ProStatAttribs, //!< Protected static member attributes
- PacTypes, //!< Package member typedefs
- PacFuncs, //!< Package member functions
- PacAttribs, //!< Package member attributes
- PacStatFuncs, //!< Package static member functions
- PacStatAttribs, //!< Package static member attributes
- PriTypes, //!< Private member typedefs
- PriFuncs, //!< Private member functions
- PriAttribs, //!< Private member attributes
- PriSlots, //!< Private Qt slots
- PriStatFuncs, //!< Private static member functions
- PriStatAttribs, //!< Private static member attributes
- Friend, //!< Friends
- Related, //!< Function marked as related
- Defines, //!< Preprocessor defines
- Prototypes, //!< Global function prototypes
- Typedefs, //!< Global typedefs
- Enums, //!< Enumerations
- Functions, //!< Global functions
- Variables //!< Global variables
- };
-
- /*! Returns a string representation of the value returned by kind() */
- virtual const IString * kindString() const = 0;
-
- /*! Returns what kind of section this is */
- virtual SectionKind kind() const = 0;
-
- /*! Returns the description attached to this section (for user defined
- * sections, also known as member groups).
- */
- virtual IDocRoot *description() const = 0;
-
- /*! Returns an iterator for the members of this section */
- virtual IMemberIterator *members() const = 0;
-
- /*! Returns \c true if this section contains statics */
- virtual bool isStatic() const = 0;
-
- /*! Returns \c true if this section belongs to a
- * public section of a class
- */
- virtual bool isPublic() const = 0;
-
- /*! Returns \c true if this section belongs to a
- * private section of a class
- */
- virtual bool isPrivate() const = 0;
-
- /*! Returns \c true if this section belongs to a
- * protected section of a class
- * */
- virtual bool isProtected() const = 0;
-};
-
-class IUserDefined : public ISection
-{
- public:
- virtual const IString * header() const = 0;
-};
-
-class ISectionIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(ISectionIterator)
- virtual ISection *toFirst() = 0;
- virtual ISection *toLast() = 0;
- virtual ISection *toNext() = 0;
- virtual ISection *toPrev() = 0;
- virtual ISection *current() const = 0;
- virtual void release() = 0;
-};
-
-/*! \brief The interface to a compound in the object model.
- *
- * A compound has a name which can be obtained via the name() method
- * and a unique id, which is return via the id() method.
- * A compound consists zero or more members which are grouped into sections.
- * The sections() method can be used to access the individual sections.
- * Alternatively, members can be obtained by name or id. There are
- * different types of compounds. The kind() method returns what kind of
- * compound this is. Depending on the return value one can dynamically
- * cast an interface pointer to an more specialised interface that provides
- * additional methods.
- * Example:
- * \code
- * ICompound *comp=...;
- * if (comp->kind()==ICompound::Class)
- * {
- * IClass *cls = dynamic_cast<IClass*>(comp);
- * // use methods of IClass
- * }
- * \endcode
- * The documentation that is provided by a compound is available via
- * the briefDescription() and detailedDescription() methods.
- * To avoid excessive memory usage, release() should be called (once) on each
- * compound interface pointer that is no longer needed.
- */
-class ICompound
-{
- public:
- VIRTUAL_DESTRUCTOR(ICompound)
- /*! Represents the kind of compounds recognised by doxygen. */
- enum CompoundKind { Invalid=0,
- Class, Struct, Union, Interface, Protocol, Category,
- Exception, File, Namespace, Group, Page, Example, Dir
- };
-
- /*! Returns the name of this compound */
- virtual const IString * name() const = 0;
-
- /*! Returns the id of this compound. The id is a
- * unique string representing a specific compound object.
- */
- virtual const IString * id() const = 0;
-
- /*! Returns the kind of compound. See #CompoundKind for possible
- * values.
- */
- virtual CompoundKind kind() const = 0;
-
- /*! Returns a string representation of the compound kind.
- * @see kind()
- */
- virtual const IString * kindString() const = 0;
-
- /*! Returns an iterator for the different member sections in this
- * compound.
- */
- virtual ISectionIterator *sections() const = 0;
-
- /*! Returns a tree-structured representation of the brief
- * description that is attached to this compound.
- */
- virtual IDocRoot *briefDescription() const = 0;
-
- /*! Returns a tree-structured representation of the detailed
- * description that is attached to this compound.
- */
- virtual IDocRoot *detailedDescription() const = 0;
-
- /*! Returns an interface to a member given its id.
- * @param id The member id.
- */
- virtual IMember *memberById(const char * id) const = 0;
-
- /*! Returns a list of all members within the compound having a certain
- * name. Member overloading is the reason why there can be more than
- * one member.
- * @param name The name of the member.
- */
- virtual IMemberIterator *memberByName(const char * name) const = 0;
-
- /*! Decreases the reference counter for this compound. If it reaches
- * zero, the memory for the compound will be released.
- */
- virtual void release() = 0;
-};
-
-class ICompoundIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(ICompoundIterator)
- virtual void toFirst() = 0;
- virtual void toLast() = 0;
- virtual void toNext() = 0;
- virtual void toPrev() = 0;
- virtual ICompound *current() const = 0;
- virtual void release() = 0;
-};
-
-class IRelatedCompound
-{
- public:
- VIRTUAL_DESTRUCTOR(IRelatedCompound)
- enum Protection { Public, Protected, Private };
- enum Kind { Normal, Virtual };
- virtual ICompound *compound() const = 0;
- virtual Protection protection() const = 0;
- virtual Kind kind() const = 0;
- virtual const IString *name() const = 0;
-
-};
-
-class IRelatedCompoundIterator
-{
- public:
- VIRTUAL_DESTRUCTOR(IRelatedCompoundIterator)
- virtual IRelatedCompound *toFirst() = 0;
- virtual IRelatedCompound *toLast() = 0;
- virtual IRelatedCompound *toNext() = 0;
- virtual IRelatedCompound *toPrev() = 0;
- virtual IRelatedCompound *current() const = 0;
- virtual void release() = 0;
-};
-
-/*! \brief The interface to a class in the object model.
- */
-class IClass : public ICompound
-{
- public:
- virtual IGraph *inheritanceGraph() const = 0;
- virtual IGraph *collaborationGraph() const = 0;
- virtual IRelatedCompoundIterator *baseCompounds() const = 0;
- virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
- virtual ICompoundIterator *nestedCompounds() const = 0;
- virtual IParamIterator *templateParameters() const = 0;
- virtual const IString *locationFile() const = 0;
- virtual int locationLine() const = 0;
- virtual const IString *locationBodyFile() const = 0;
- virtual int locationBodyStartLine() const = 0;
- virtual int locationBodyEndLine() const = 0;
-
- // TODO:
- // class:
- // listOfAllMembers()
- // protection()
- // isAbstract()
-};
-
-/*! \brief The interface to a struct in the object model.
- */
-class IStruct : public ICompound
-{
- public:
- virtual ICompoundIterator *nestedCompounds() const = 0;
- virtual IRelatedCompoundIterator *baseCompounds() const = 0;
- virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
- virtual const IString *locationFile() const = 0;
- virtual int locationLine() const = 0;
- virtual int locationBodyStartLine() const = 0;
- virtual int locationBodyEndLine() const = 0;
-};
-
-/*! \brief The interface to a union in the object model.
- */
-class IUnion : public ICompound
-{
- public:
- virtual ICompoundIterator *nestedCompounds() const = 0;
-};
-
-/*! \brief The interface to a Java/IDL interface in the object model.
- */
-class IInterface : public ICompound
-{
- public:
- virtual IRelatedCompoundIterator *baseCompounds() const = 0;
- virtual IRelatedCompoundIterator *derivedCompounds() const = 0;
-};
-
-
-/*! \brief The interface to a Java/IDL exception in the object model.
- */
-class IException : public ICompound
-{
-};
-
-/*! \brief The interface to a namespace in the object model.
- */
-class INamespace : public ICompound
-{
- public:
- virtual ICompoundIterator *nestedCompounds() const = 0;
-};
-
-/*! \brief The interface to a file in the object model.
- */
-class IFile : public ICompound
-{
- public:
- virtual IGraph *includeDependencyGraph() const = 0;
- virtual IGraph *includedByDependencyGraph() const = 0;
- virtual IDocProgramListing *source() const = 0;
- virtual ICompoundIterator *nestedCompounds() const = 0;
-
- virtual IIncludeIterator *includes() const = 0;
- virtual IIncludeIterator *includedBy() const = 0;
-
- // ICompound *innerNamespaces()
- // ICompoundIterator *innerClasses()
-};
-
-/*! \brief The interface to a group in the object model.
- */
-class IGroup : public ICompound
-{
- public:
- virtual ICompoundIterator *nestedCompounds() const = 0;
- // group:
- // Title()
- // innerFile()
- // innerPage()
-};
-
-/*! \brief The interface to a page in the object model.
- */
-class IPage : public ICompound
-{
- public:
- virtual const IDocTitle *title() const = 0;
-};
-
-/** \brief Interface to a directory in the object model. */
-class IDir : public ICompound
-{
- public:
- virtual ICompoundIterator *nestedCompounds() const = 0;
-};
-
-/*! Root node of the object model. */
-class IDoxygen
-{
- public:
- VIRTUAL_DESTRUCTOR(IDoxygen)
-
- /*! Returns an iterator that can be used to iterate over the list
- * of compounds found in the project.
- */
- virtual ICompoundIterator *compounds() const = 0;
-
- /*! Returns a compound given its unique \a id. If you have a
- * compound id this function is much more efficient than iterating
- * over the compound list. Returns 0 if the id is not valid.
- */
- virtual ICompound *compoundById(const char * id) const = 0;
-
- /*! Returns a compound given its name (including the scope).
- * Returns 0 if the name is not found in the project.
- */
- virtual ICompound *compoundByName(const char * name) const = 0;
-
- /*! Returns an interface to a compound containing a member given it the
- * member's id. Given the ICompound interface one can use the same id
- * to obtain the IMember interface.
- * @param id The member id.
- */
- virtual ICompound *memberById(const char * id) const = 0;
-
- /*! Returns a list of all compounds containing at least one members
- * with a certain name. Each compound can be asked to return the
- * list of members with that name.
- * @param name The name of the member.
- */
- virtual ICompoundIterator *memberByName(const char * name) const = 0;
-
- /*! Releases the memory for the object hierarchy obtained by
- * createdObjecModelFromXML(). First release all iterators before calling
- * this function.
- */
- virtual void release() = 0;
-
- /*! Sets the debug level.
- * - 0 all debugging messages are disabled (the default).
- * - 1 display important messages only
- * - 2 display any messages.
- */
- virtual void setDebugLevel(int level) = 0;
-
- /*! Reads an XML directory produced by doxygen and builds up a data
- * structure representing the contents of the XML files in the directory.
- */
- virtual bool readXMLDir(const char *xmlDirName) = 0;
-};
-
-/*! Factory method that creates an empty object model for a doxygen generated XML file.
- * Use the readXMLDir() method to build the model from an XML output
- * directory containing doxygen output.
- */
-IDoxygen *createObjectModel();
-
-#endif
diff --git a/addon/doxmlparser/src/loamhandler.cpp b/addon/doxmlparser/src/loamhandler.cpp
index a939b7b..52aa576 100644
--- a/addon/doxmlparser/src/loamhandler.cpp
+++ b/addon/doxmlparser/src/loamhandler.cpp
@@ -1,5 +1,7 @@
#include "loamhandler.h"
#include "memberhandler.h"
+#include "linkedtexthandler.h"
+#include "paramhandler.h"
ListOfAllMembersHandler::ListOfAllMembersHandler(IBaseHandler *parent) : m_parent(parent)
diff --git a/addon/doxmlparser/src/mainhandler.cpp b/addon/doxmlparser/src/mainhandler.cpp
index 93525f0..ac56229 100644
--- a/addon/doxmlparser/src/mainhandler.cpp
+++ b/addon/doxmlparser/src/mainhandler.cpp
@@ -20,6 +20,8 @@
#include "graphhandler.h"
#include "dochandler.h"
#include "memberhandler.h"
+#include "linkedtexthandler.h"
+#include "paramhandler.h"
#include "debug.h"
diff --git a/addon/doxmlparser/src/sectionhandler.cpp b/addon/doxmlparser/src/sectionhandler.cpp
index 1137901..075cc73 100644
--- a/addon/doxmlparser/src/sectionhandler.cpp
+++ b/addon/doxmlparser/src/sectionhandler.cpp
@@ -17,6 +17,8 @@
#include "compoundhandler.h"
#include "sectionhandler.h"
#include "memberhandler.h"
+#include "linkedtexthandler.h"
+#include "paramhandler.h"
#include "dochandler.h"
#include "debug.h"
diff --git a/addon/doxmlparser/test/CMakeLists.txt b/addon/doxmlparser/test/CMakeLists.txt
new file mode 100644
index 0000000..c38c8a5
--- /dev/null
+++ b/addon/doxmlparser/test/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+include_directories(
+ ../include
+ ${CMAKE_SOURCE_DIR}/qtools
+)
+
+add_executable(doxmlparser_test
+main.cpp
+)
+
+
+target_link_libraries(doxmlparser_test
+ doxmlparser
+ qtools
+)
diff --git a/addon/doxmlparser/test/Makefile.in b/addon/doxmlparser/test/Makefile.in
deleted file mode 100644
index 87b1829..0000000
--- a/addon/doxmlparser/test/Makefile.in
+++ /dev/null
@@ -1,15 +0,0 @@
-all clean depend: Makefile.xmlparse
- $(MAKE) -f Makefile.xmlparse $@
-
-distclean: clean
- $(RM) -rf Makefile.xmlparse xmlparse.pro Makefile obj
-
-realclean: distclean
-
-tmake:
- $(ENV) $(PERL) $(TMAKE) xmlparse.pro >Makefile.xmlparse
-
-Makefile.xmlparse: xmlparse.pro
- $(ENV) $(PERL) $(TMAKE) xmlparse.pro >Makefile.xmlparse
-
-install:
diff --git a/addon/doxmlparser/test/xmlparse.pro.in b/addon/doxmlparser/test/xmlparse.pro.in
deleted file mode 100644
index 368d499..0000000
--- a/addon/doxmlparser/test/xmlparse.pro.in
+++ /dev/null
@@ -1,20 +0,0 @@
-TEMPLATE = app.t
-CONFIG = console warn_on $extraopts
-HEADERS =
-SOURCES = main.cpp
-unix:LIBS += -L../../../lib -ldoxmlparser -lqtools
-win32:INCLUDEPATH += .
-win32-mingw:LIBS += -L../../../lib -ldoxmlparser -lqtools
-win32-msvc:LIBS += doxmlparser.lib qtools.lib shell32.lib
-win32-msvc:TMAKE_LFLAGS += /LIBPATH:..\..\..\lib;..\lib
-win32-borland:LIBS += doxmlparser.lib qtools.lib shell32.lib
-win32-borland:TMAKE_LFLAGS += -L..\..\..\lib
-win32:TMAKE_CXXFLAGS += -DQT_NODLL
-DESTDIR = ../../../bin
-OBJECTS_DIR = ../../../objects/doxmlparser/test
-TARGET = xmlparse
-INCLUDEPATH += ../../../qtools ../include
-DEPENDPATH += ../include
-unix:TARGETDEPS = ../../../lib/libdoxmlparser.a
-win32:TARGETDEPS = ..\..\..\lib\doxmlparser.lib
-
diff --git a/addon/doxyapp/CMakeLists.txt b/addon/doxyapp/CMakeLists.txt
index 84c0ee8..f205664 100644
--- a/addon/doxyapp/CMakeLists.txt
+++ b/addon/doxyapp/CMakeLists.txt
@@ -1,11 +1,3 @@
-# configvalues.h
-add_custom_command(
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maph ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.h
- DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py
- OUTPUT ${GENERATED_SRC}/configvalues.h
-)
-set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
-
find_package(Iconv)
include_directories(
@@ -20,10 +12,17 @@ include_directories(
add_executable(doxyapp
doxyapp.cpp
)
+
+if (use_libclang)
+ set(CLANG_LIBS libclang clangTooling ${llvm_libs})
+endif()
+
target_link_libraries(doxyapp
_doxygen
qtools
md5
+lodepng
+mscgen
version
doxycfg
vhdlparser
diff --git a/addon/doxyapp/doxyapp.cpp b/addon/doxyapp/doxyapp.cpp
index 1249871..dd092ed 100644
--- a/addon/doxyapp/doxyapp.cpp
+++ b/addon/doxyapp/doxyapp.cpp
@@ -60,7 +60,7 @@ class XRefDummyCodeGenerator : public CodeOutputInterface
void startFontClass(const char *) {}
void endFontClass() {}
void writeCodeAnchor(const char *) {}
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
// here we are presented with the symbols found by the code parser
diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt
index 498169f..e76f031 100644
--- a/addon/doxyparse/CMakeLists.txt
+++ b/addon/doxyparse/CMakeLists.txt
@@ -1,11 +1,3 @@
-# configvalues.h
-add_custom_command(
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maph ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.h
- DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py
- OUTPUT ${GENERATED_SRC}/configvalues.h
-)
-set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
-
find_package(Iconv)
include_directories(
@@ -20,10 +12,17 @@ include_directories(
add_executable(doxyparse
doxyparse.cpp
)
+
+if (use_libclang)
+ set(CLANG_LIBS libclang clangTooling ${llvm_libs})
+endif()
+
target_link_libraries(doxyparse
_doxygen
qtools
md5
+lodepng
+mscgen
version
doxycfg
vhdlparser
diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp
index 584e8b0..26ecea9 100644
--- a/addon/doxyparse/doxyparse.cpp
+++ b/addon/doxyparse/doxyparse.cpp
@@ -19,7 +19,11 @@
*/
#include <stdlib.h>
-#include <unistd.h>
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ #include <unistd.h>
+#else
+ #include <windows.h>
+#endif
#include "doxygen.h"
#include "outputgen.h"
#include "parserintf.h"
@@ -35,6 +39,7 @@
#include <cstdlib>
#include <sstream>
#include <map>
+#include <qdir.h>
class Doxyparse : public CodeOutputInterface
{
@@ -58,7 +63,7 @@ class Doxyparse : public CodeOutputInterface
const char *,const char *,const SourceLinkInfo &,
const SourceLinkInfo &) {}
void startCodeLine(bool) {}
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
void linkableSymbol(int l, const char *sym, Definition *symDef, Definition *context)
@@ -159,9 +164,6 @@ static void printReferenceTo(std::string type, std::string signature, std::strin
printf(" type: %s\n", type.c_str());
printf(" defined_in: %s\n", defined_in.c_str());
}
-static void printNumberOfConditionalPaths(MemberDef* md) {
- printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords());
-}
static int isPartOfCStruct(MemberDef * md) {
return is_c_code && md->getClassDef() != NULL;
@@ -242,7 +244,6 @@ void functionInformation(MemberDef* md) {
printNumberOfLines(size);
ArgumentList *argList = md->argumentList();
printNumberOfArguments(argList->count());
- printNumberOfConditionalPaths(md);
MemberSDict *defDict = md->getReferencesMembers();
if (defDict) {
MemberSDict::Iterator msdi(*defDict);
@@ -258,7 +259,7 @@ void functionInformation(MemberDef* md) {
static void lookupSymbol(Definition *d) {
if (d->definitionType() == Definition::TypeMember) {
- MemberDef *md = (MemberDef *)d;
+ MemberDef *md = dynamic_cast<MemberDef*>(d);
std::string type = md->memberTypeName().data();
std::string signature = functionSignature(md);
printDefinition(type, signature, md->getDefLine());
@@ -388,7 +389,12 @@ int main(int argc,char **argv) {
// we need a place to put intermediate files
std::ostringstream tmpdir;
- tmpdir << "/tmp/doxyparse-" << getpid();
+#if !defined(_WIN32) || defined(__CYGWIN__)
+ unsigned int pid = (uint)getpid();
+#else
+ unsigned int pid = (uint)GetCurrentProcessId();
+#endif
+ tmpdir << "/tmp/doxyparse-" << pid;
Config_getString(OUTPUT_DIRECTORY)= tmpdir.str().c_str();
// enable HTML (fake) output to omit warning about missing output format
Config_getBool(GENERATE_HTML)=TRUE;
@@ -449,11 +455,14 @@ int main(int argc,char **argv) {
}
}
+ QDir thisDir;
// remove temporary files
- if (!Doxygen::objDBFileName.isEmpty()) unlink(Doxygen::objDBFileName);
- if (!Doxygen::entryDBFileName.isEmpty()) unlink(Doxygen::entryDBFileName);
+ if (!Doxygen::objDBFileName.isEmpty()) thisDir.remove(Doxygen::objDBFileName);
+ if (!Doxygen::entryDBFileName.isEmpty()) thisDir.remove(Doxygen::entryDBFileName);
+ if (!Doxygen::filterDBFileName.isEmpty()) thisDir.remove(Doxygen::filterDBFileName);
+
// clean up after us
- rmdir(Config_getString(OUTPUT_DIRECTORY));
+ thisDir.rmdir(Config_getString(OUTPUT_DIRECTORY));
listSymbols();
diff --git a/addon/doxysearch/doxysearch.cpp b/addon/doxysearch/doxysearch.cpp
index 1c4effd..98adab4 100644
--- a/addon/doxysearch/doxysearch.cpp
+++ b/addon/doxysearch/doxysearch.cpp
@@ -367,12 +367,24 @@ int main(int argc,char **argv)
// create query
Xapian::Database db(indexDir);
Xapian::Enquire enquire(db);
- Xapian::Query query;
+
std::vector<std::string> words = split(searchFor,' ');
- for (std::vector<std::string>::const_iterator it=words.begin();it!=words.end();++it)
- {
- query = Xapian::Query(Xapian::Query::OP_OR,query,Xapian::Query(*it));
- }
+ Xapian::QueryParser parser;
+ parser.set_database(db);
+ parser.set_default_op(Xapian::Query::OP_AND);
+ parser.set_stemming_strategy(Xapian::QueryParser::STEM_ALL);
+ Xapian::termcount max_expansion=100;
+#if (XAPIAN_MAJOR_VERSION==1) && (XAPIAN_MINOR_VERSION==2)
+ parser.set_max_wildcard_expansion(max_expansion);
+#else
+ parser.set_max_expansion(max_expansion,Xapian::Query::WILDCARD_LIMIT_MOST_FREQUENT);
+#endif
+ Xapian::Query query=parser.parse_query(searchFor,
+ Xapian::QueryParser::FLAG_DEFAULT |
+ Xapian::QueryParser::FLAG_WILDCARD |
+ Xapian::QueryParser::FLAG_PHRASE |
+ Xapian::QueryParser::FLAG_PARTIAL
+ );
enquire.set_query(query);
// get results
diff --git a/appveyor.yml b/appveyor.yml
index 0cea036..d18474f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -14,22 +14,25 @@ environment:
- VSVERSION: "15 2017"
- VSVERSION: "14 2015"
+cache:
+ - C:\Users\Appveyor\.conan -> appveyor.yml
+ - c:\.conan -> appveyor.yml
+ - '%LOCALAPPDATA%\pip\Cache -> appveyor.yml'
+ - C:\miktex-repository -> appveyor.yml
+
+
init:
- cmake --version
- perl --version
- msbuild /version
install:
- - ps: Invoke-WebRequest http://doxygen.nl/testing/miktex.zip -OutFile miktex.zip
- - 7z x miktex.zip -oC:\deps\miktex
-# Disabled MikTeX installed due to unreliable download
-# - ps: Invoke-WebRequest https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs924/gs924w32.exe -OutFile gswin32c.exe
-# - gswin32c /S /D=C:\deps\ghostscript
-# - ps: if($env:platform -eq "x64") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x64.zip -OutFile miktexsetup.zip }
-# - ps: if($env:platform -eq "Win32") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x86.zip -OutFile miktexsetup.zip }
-# - 7z x miktexsetup.zip -oC:\tmpmiktex
-# - C:\tmpmiktex\miktexsetup --local-package-repository=C:\temp\miktex --package-set=basic download
-# - C:\tmpmiktex\miktexsetup --verbose --local-package-repository=C:\temp\miktex --package-set=basic install
+ # Static url: https://github.com/MiKTeX/miktex/issues/321#issuecomment-496286866
+ # The setup is small enough, and does not need to be cached
+ - appveyor DownloadFile https://miktex.org/download/win/miktexsetup-x64.zip
+ - 7z e miktexsetup-x64.zip
+ - miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential download
+ - miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential --shared install
- refreshenv
- pip install conan
- ps: |
@@ -38,7 +41,6 @@ install:
winflexbison/2.5.16@bincrafters/stable" | Out-File -Encoding ASCII -FilePath conanfile.txt
- conan install . -g virtualrunenv --build missing
- activate_run.bat
- - set "PATH=%PATH%;C:\deps\ghostscript\bin;C:\deps\miktex\miktex\bin"
before_build:
- if "%platform%"=="Win32" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION%" )
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 4c0a19d..7697d70 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -45,7 +45,6 @@ EXAMPLE_PATH = ../examples
RECURSIVE = NO
TAGFILES =
ALLEXTERNALS = NO
-PERL_PATH = /usr/bin/perl
SEARCHENGINE = NO
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
diff --git a/doc/commands.doc b/doc/commands.doc
index ae27a7a..6c8b696 100644
--- a/doc/commands.doc
+++ b/doc/commands.doc
@@ -29,9 +29,14 @@ Each argument has a certain range:
<li>If (round) braces are used the argument extends until the end of the line
on which the command was found.
<li>If {curly} braces are used the argument extends until the next paragraph.
- Paragraphs are delimited by a blank line or by a section indicator.
+ Paragraphs are delimited by a blank line or by a section indicator. Note that
+ {curly} braces are also used for command options, here the braces are mandatory
+ and just 'normal' characters. The starting curly brace has to directly follow
+ the command, so without whitspace.
</ul>
-If in addition to the above argument specifiers [square] brackets are used the argument is optional.
+If in addition to the above argument specifiers [square] brackets are used the argument
+is optional, unless they are placed between quotes in that case they are a mandatory
+part of the command argument.
Here is an alphabetically sorted list of all commands with references to their
documentation:
@@ -516,7 +521,7 @@ Structural indicators
\endlatexonly
<hr>
-\section cmdexample \\example[{lineno}] <file-name>
+\section cmdexample \\example['{lineno}'] <file-name>
\addindex \\example
Indicates that a comment block contains documentation for a source code
@@ -1607,7 +1612,7 @@ ALIASES = "english=\if english" \
\endlatexonly
<hr>
-\section cmdparam \\param [(dir)] <parameter-name> { parameter description }
+\section cmdparam \\param '['dir']' <parameter-name> { parameter description }
\addindex \\param
Starts a parameter description for a function parameter with name
@@ -1616,7 +1621,7 @@ ALIASES = "english=\if english" \
the documentation of this (or any other) parameter is missing or not
present in the function declaration or definition.
- The \c \\param command has an optional attribute, (dir), specifying the direction
+ The \c \\param command has an optional attribute, `dir`, specifying the direction
of the parameter. Possible values are "[in]", "[in,out]", and "[out]",
note the [square] brackets in this description.
When a parameter is both input and output, [in,out] is used as attribute.
@@ -2186,7 +2191,7 @@ Commands for displaying examples
\htmlonly</p></center><p>\endhtmlonly
<hr>
-\section cmddontinclude \\dontinclude[{lineno}] <file-name>
+\section cmddontinclude \\dontinclude['{lineno}'] <file-name>
\addindex \\dontinclude
This command can be used to parse a source file without actually
@@ -2227,7 +2232,7 @@ Commands for displaying examples
\ref cmdinclude "\\include".
<hr>
-\section cmdinclude \\include[{lineno|doc}] <file-name>
+\section cmdinclude \\include['{'option'}'] <file-name>
\addindex \\include
This command can be used to include a source file as a block of code.
@@ -2261,9 +2266,9 @@ Commands for displaying examples
\note Doxygen's special commands do not work inside blocks of code.
It is allowed to nest C-style comments inside a code block though.
- You can add option `{lineno}` to enable line numbers for the included code if desired.
-
- You can add option `{doc}` to treat the file as documentation rather than code.
+ The `option` can either be `lineno` or `doc`.
+ The `option` `lineno` can be used to enable line numbers for the included code if desired.
+ The `option` `doc` can be used to treat the file as documentation rather than code.
\note Some that when using the `{doc}` option,
commands like \ref cmdcond "\\cond" and \ref cmdif "\\if" don't work with
@@ -2350,7 +2355,7 @@ Commands for displaying examples
See section \ref cmddontinclude "\\dontinclude" for an example.
<hr>
-\section cmdsnippet \\snippet[{lineno|doc}] <file-name> ( block_id )
+\section cmdsnippet \\snippet['{'option'}'] <file-name> ( block_id )
\addindex \\snippet
Where the \ref cmdinclude "\\include" command can be used to include
@@ -2393,9 +2398,9 @@ Commands for displaying examples
Note also that the [block_id] markers should appear exactly twice in the
source file.
- You can add option `{lineno}` to enable line numbers for the snippet if desired.
-
- You can add option `{doc}` to treat the file as documentation rather than code.
+ The `option` can either be `lineno` or `doc`.
+ The `option` `lineno` can be used to enable line numbers for the included code if desired.
+ The `option` `doc` can be used to treat the file as documentation rather than code.
\note Some that when using the `{doc}` option,
commands like \ref cmdcond "\\cond" and \ref cmdif "\\if" don't work with
@@ -2574,7 +2579,7 @@ Commands for visual enhancements
To have multiple words in typewriter font use \<tt\>multiple words\</tt\>.
<hr>
-\section cmdcode \\code [ '{'<word>'}']
+\section cmdcode \\code['{'<word>'}']
\addindex \\code
Starts a block of code. A code block is treated differently
@@ -2778,9 +2783,9 @@ See also the \ref emojisup "emoji support page" for details.
\note The text fragment should only include the part of the message
sequence chart that is
- within the <code>msc {...}</code> block.
- \note You need to install the <code>mscgen</code> tool, if you want to use this
- command.
+ within the <code>msc {...}</code> block (this is different from
+ \ref cmdmscfile "\\mscfile").
+ \note mscgen is now built in into doxygen
Here is an example of the use of the \c \\msc command.
\code
@@ -2918,7 +2923,7 @@ class Receiver
The first argument specifies the file name of the image.
doxygen will look for files in the paths (or files) that you specified
after the \ref cfg_mscfile_dirs "MSCFILE_DIRS" tag.
- If the msc file is found it will be used as an input file to the mscgen tool.
+ If the msc file is found it will be used as an input file to the built in mscgen tool.
The resulting image will be put into the correct output directory.
If the msc file name contains spaces you'll have to put quotes ("...") around it.
@@ -2933,6 +2938,10 @@ class Receiver
\ref image_sizeindicator "Size indication" with the
\ref cmdimage "\\image" command.
+ \note The text fragment should include the part message of the
+ sequence chart as well as the starting `msc {` and ending `}`
+ (this is different from \ref cmdmsc "\\msc").
+
\sa section \ref cmdmsc "\\msc".
<hr>
@@ -3152,7 +3161,7 @@ class Receiver
\ref cmdhtmlinclude "\\htmlinclude".
<hr>
-\section cmdimage \\image['{'[option]'}'] <format> <file> ["caption"] [<sizeindication>=<size>]
+\section cmdimage \\image['{'option'}'] <format> <file> ["caption"] [<sizeindication>=<size>]
\addindex \\image
Inserts an image into the documentation. This command is format
diff --git a/doc/docblocks.doc b/doc/docblocks.doc
index d4eab5d..9d14f6e 100644
--- a/doc/docblocks.doc
+++ b/doc/docblocks.doc
@@ -123,6 +123,25 @@ or
/////////////////////////////////////////////////
\endverbatim
+or
+
+\verbatim
+/************************************************
+ * ... text
+ ***********************************************/
+\endverbatim
+
+as long as JAVADOC_BANNER = YES is used.
+\include javadoc-banner.h
+ \htmlonly
+ Click <a href="examples/javadoc-banner/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by doxygen.
+ \endhtmlonly
+ \latexonly
+ See \hyperlink{javadoc_banner_example}{Javadoc Banner example}
+ for the corresponding \mbox{\LaTeX} documentation that is generated by doxygen.
+ \endlatexonly
+
</ol>
For the brief description there are also several possibilities:
diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex
index 1a44574..078bdea 100644
--- a/doc/doxygen_manual.tex
+++ b/doc/doxygen_manual.tex
@@ -14,6 +14,14 @@
\batchmode
\documentclass{book}
+%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package
+\usepackage{ifthen}
+\ifx\requestedLaTeXdate\undefined
+\usepackage{array}
+\else
+\usepackage{array}[=2016-10-06]
+\fi
+%%
\usepackage[a4paper,left=2.5cm,right=2.5cm,top=2.5cm,bottom=2.5cm]{geometry}
\usepackage{makeidx}
\usepackage{natbib}
@@ -23,7 +31,7 @@
\usepackage{geometry}
\usepackage{listings}
\usepackage{color}
-\usepackage{ifthen}
+%%\usepackage{ifthen} %% moved to top due to workaround for LaTex 2019 version and unmaintained tabu package
\usepackage[table]{xcolor}
\PassOptionsToPackage{warn}{textcomp}
\usepackage{textcomp}
@@ -57,6 +65,16 @@
\usepackage{amssymb}
\usepackage{doxygen}
\usepackage{manual}
+%%
+\makeatletter
+\newenvironment{DoxygenSubAppendix}{%
+ \renewcommand{\doxysection}{\@ifstar{\doxysubsection@star}{\doxysubsection@nostar}}%
+ \renewcommand{\doxysubsection}{\@ifstar{\doxysubsubsection@star}{\doxysubsubsection@nostar}}
+ \renewcommand{\doxysubsubsection}{\@ifstar{\doxyparagraph@star}{\doxyparagraph@nostar}}
+ \renewcommand{\doxyparagraph}{\@ifstar{\doxysubparagraph@star}{\doxysubparagraph@nostar}}
+}{}
+\makeatother
+%%
\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}}
\lstset{language=C++,inputencoding=utf8,basicstyle=\footnotesize,breaklines=true,breakatwhitespace=true,tabsize=8,numbers=left }
\makeindex
@@ -147,22 +165,42 @@ Written by Dimitri van Heesch\\[2ex]
\subinputfrom{../html/examples/group/latex/}{refman_doc}
\chapter{Member Groups Example}\label{memgrp_example}\hypertarget{memgrp_example}{}
\subinputfrom{../html/examples/memgrp/latex/}{refman_doc}
-\chapter{After Block Example}\label{afterdoc_example}\hypertarget{afterdoc_example}{}
-\subinputfrom{../html/examples/afterdoc/latex/}{refman_doc}
-\chapter{QT Style Example}\label{qtstyle_example}\hypertarget{qtstyle_example}{}
-\subinputfrom{../html/examples/qtstyle/latex/}{refman_doc}
-\chapter{Javadoc Style Example}\label{jdstyle_example}\hypertarget{jdstyle_example}{}
-\subinputfrom{../html/examples/jdstyle/latex/}{refman_doc}
+\chapter{Style Examples}
+ \doxysection{After Block Example}\label{afterdoc_example}\hypertarget{afterdoc_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/afterdoc/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{QT Style Example}\label{qtstyle_example}\hypertarget{qtstyle_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/qtstyle/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{Javadoc Style Example}\label{jdstyle_example}\hypertarget{jdstyle_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/jdstyle/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{Javadoc Banner Example}\label{javadoc_banner_example}\hypertarget{javadoc_banner_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/javadoc-banner/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
\chapter{Structural Commands Example}\label{structcmd_example}\hypertarget{structcmd_example}{}
\subinputfrom{../html/examples/structcmd/latex/}{refman_doc}
-\chapter{Python Docstring Example}\label{python_example}\hypertarget{python_example}{}
-\subinputfrom{../html/examples/docstring/latex/}{refman_doc}
-\chapter{Python Example}\label{py_example}\hypertarget{py_example}{}
-\subinputfrom{../html/examples/pyexample/latex/}{refman_doc}
-\chapter{VHDL Example}\label{vhdl_example}\hypertarget{vhdl_example}{}
-\subinputfrom{../html/examples/mux/latex/}{refman_doc}
-\chapter{Tcl Example}\label{tcl_example}\hypertarget{tcl_example}{}
-\subinputfrom{../html/examples/tclexample/latex/}{refman_doc}
+\chapter{Language Examples}
+ \doxysection{Python Docstring Example}\label{python_example}\hypertarget{python_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/docstring/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{Python Example}\label{py_example}\hypertarget{py_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/pyexample/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{VHDL Example}\label{vhdl_example}\hypertarget{vhdl_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/mux/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
+ \doxysection{Tcl Example}\label{tcl_example}\hypertarget{tcl_example}{}
+ \begin{DoxygenSubAppendix}
+ \subinputfrom{../html/examples/tclexample/latex/}{refman_doc}
+ \end{DoxygenSubAppendix}
\chapter{Class Example}\label{class_example}\hypertarget{class_example}{}
\subinputfrom{../html/examples/class/latex/}{refman_doc}
diff --git a/doc/faq.doc b/doc/faq.doc
index 88a1275..0ba9450 100644
--- a/doc/faq.doc
+++ b/doc/faq.doc
@@ -235,6 +235,13 @@ should send me a code fragment that triggers the message. To work around
the problem, put some line-breaks into your file, split it up into smaller
parts, or exclude it from the input using EXCLUDE.
+Another way to work around this problem is to use the cmake command with the option:
+```
+-Denlarge_lex_buffers=<size>
+```
+where `<size>` is the new size of the input (`YY_BUF_SIZE`) and read (`YY_READ_BUF_SIZE`) buffer.
+In case this option is not given the default value of 262144 (i.e. 256K) will be used.
+
\section faq_latex When running make in the latex directory I get "TeX capacity exceeded". Now what?
You can edit the texmf.cfg file to increase the default values of the
diff --git a/doc/install.doc b/doc/install.doc
index 18ea44e..b711cd4 100644
--- a/doc/install.doc
+++ b/doc/install.doc
@@ -201,7 +201,7 @@ tar zxvf doxygen-x.y.z.src.tar.gz
\endverbatim
to unpack the sources (you can obtain \c tar from e.g. http://gnuwin32.sourceforge.net/packages.html).
Alternatively you can use an unpack program, like 7-Zip (see https://www.7-zip.org/)
-or use the build in unpack feature of modern Windows systems).
+or use the built-in unpack feature of modern Windows systems).
Now your environment is setup to generate the required project files for \c doxygen.
diff --git a/doc/trouble.doc b/doc/trouble.doc
index c490ae1..cb50399 100644
--- a/doc/trouble.doc
+++ b/doc/trouble.doc
@@ -20,7 +20,7 @@
<ul>
<li>Doxygen is <em>not</em> a real compiler, it is only a lexical scanner.
This means that it can and will not detect errors in your source code.
-<li>Doxygen has a build in preprocessor, but this works slightly different than
+<li>Doxygen has a built-in preprocessor, but this works slightly different than
the C preprocessor. Doxygen assumes a header file is properly guarded against
multiple inclusion, and that each include file is standalone (i.e. it could be placed
at the top of a source file without causing compiler errors). As long as this is
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 0f34c6d..967f3d4 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -23,6 +23,7 @@ add_custom_target(examples
${PROJECT_BINARY_DIR}/html/examples/enum/html/index.html
${PROJECT_BINARY_DIR}/html/examples/file/html/index.html
${PROJECT_BINARY_DIR}/html/examples/func/html/index.html
+ ${PROJECT_BINARY_DIR}/html/examples/javadoc-banner/html/index.html
${PROJECT_BINARY_DIR}/html/examples/page/html/index.html
${PROJECT_BINARY_DIR}/html/examples/relates/html/index.html
${PROJECT_BINARY_DIR}/html/examples/author/html/index.html
@@ -85,6 +86,13 @@ add_custom_command(
)
add_custom_command(
+ COMMAND ${EXECUTABLE_OUTPUT_PATH}/doxygen javadoc-banner.cfg
+ COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/html/examples/javadoc-banner/latex/refman.tex > ${PROJECT_BINARY_DIR}/html/examples/javadoc-banner/latex/refman_doc.tex
+ DEPENDS doxygen javadoc-banner.h javadoc-banner.cfg ${TOP}/examples/strip_example.py
+ OUTPUT ${PROJECT_BINARY_DIR}/html/examples/javadoc-banner/html/index.html ${PROJECT_BINARY_DIR}/html/examples/javadoc-banner/latex/refman_doc.tex
+)
+
+add_custom_command(
COMMAND ${EXECUTABLE_OUTPUT_PATH}/doxygen page.cfg
COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/html/examples/page/latex/refman.tex > ${PROJECT_BINARY_DIR}/html/examples/page/latex/refman_doc.tex
DEPENDS doxygen page.doc page.cfg ${TOP}/examples/strip_example.py
diff --git a/examples/javadoc-banner.cfg b/examples/javadoc-banner.cfg
new file mode 100644
index 0000000..d650dbc
--- /dev/null
+++ b/examples/javadoc-banner.cfg
@@ -0,0 +1,15 @@
+PROJECT_NAME = "Javadoc Banner"
+OUTPUT_DIRECTORY = ../html/examples/javadoc-banner
+GENERATE_LATEX = YES
+GENERATE_MAN = NO
+GENERATE_RTF = NO
+CASE_SENSE_NAMES = NO
+INPUT = javadoc-banner.h
+STRIP_CODE_COMMENTS = NO
+QUIET = YES
+JAVADOC_AUTOBRIEF = YES
+JAVADOC_BANNER = YES
+SEARCHENGINE = NO
+COMPACT_LATEX = YES
+LATEX_HIDE_INDICES = YES
+EXTRACT_ALL = YES
diff --git a/examples/javadoc-banner.h b/examples/javadoc-banner.h
new file mode 100644
index 0000000..bc413bb
--- /dev/null
+++ b/examples/javadoc-banner.h
@@ -0,0 +1,45 @@
+/**
+ * A brief history of JavaDoc-style (C-style) comments.
+ *
+ * This is the typical JavaDoc-style C-style comment. It starts with two
+ * asterisks.
+ *
+ * @param theory Even if there is only one possible unified theory. it is just a
+ * set of rules and equations.
+ */
+void cstyle( int theory );
+
+/*******************************************************************************
+ * A brief history of JavaDoc-style (C-style) banner comments.
+ *
+ * This is the typical JavaDoc-style C-style "banner" comment. It starts with
+ * a forward slash followed by some number, n, of asterisks, where n > 2. It's
+ * written this way to be more "visible" to developers who are reading the
+ * source code.
+ *
+ * Often, developers are unaware that this is not (by default) a valid Doxygen
+ * comment block!
+ *
+ * However, as long as JAVADOC_BLOCK = YES is added to the Doxyfile, it will
+ * work as expected.
+ *
+ * This style of commenting behaves well with clang-format.
+ *
+ * @param theory Even if there is only one possible unified theory. it is just a
+ * set of rules and equations.
+ ******************************************************************************/
+void javadocBanner( int theory );
+
+/***************************************************************************//**
+ * A brief history of Doxygen-style banner comments.
+ *
+ * This is a Doxygen-style C-style "banner" comment. It starts with a "normal"
+ * comment and is then converted to a "special" comment block near the end of
+ * the first line. It is written this way to be more "visible" to developers
+ * who are reading the source code.
+ * This style of commenting behaves poorly with clang-format.
+ *
+ * @param theory Even if there is only one possible unified theory. it is just a
+ * set of rules and equations.
+ ******************************************************************************/
+void doxygenBanner( int theory );
diff --git a/examples/tag.cfg b/examples/tag.cfg
index 823b5a7..12b3c5b 100644
--- a/examples/tag.cfg
+++ b/examples/tag.cfg
@@ -6,7 +6,6 @@ GENERATE_RTF = NO
CASE_SENSE_NAMES = NO
INPUT = tag.cpp
TAGFILES = example.tag=../../example/html
-PERL_PATH = perl
QUIET = YES
JAVADOC_AUTOBRIEF = YES
SEARCHENGINE = NO
diff --git a/jquery/Makefile b/jquery/Makefile
index 5d3fedf..4da7f94 100644
--- a/jquery/Makefile
+++ b/jquery/Makefile
@@ -1,4 +1,4 @@
-JQUERY_VERSION = 3.3.1
+JQUERY_VERSION = 3.4.1
JQUERY_UI_VERSION = 1.12.1
SCROLL_VERSION = 2.1.2
POWERTIP_VERSION = 1.3.1
@@ -9,7 +9,7 @@ MINIFIER ?= /usr/local/bin/yuicompressor-2.4.7
SCRIPTS = jquery-$(JQUERY_VERSION).min.js \
jquery.ui-$(JQUERY_UI_VERSION).min.js \
jquery.scrollTo-$(SCROLL_VERSION).min.js \
- jquery.powertip-$(POWERTIP_VERSION).min.js \
+ jquery.powertip-$(POWERTIP_VERSION).mod.min.js \
jquery.ui.touch-punch-$(TOUCHPUNCH_VERSION).min.js \
jquery.smartmenus-$(SMARTMENUS_VERSION).min.js
RESULTS = jquery.js doxmenu-min.css
diff --git a/jquery/README b/jquery/README
index 881daad..6f39c34 100644
--- a/jquery/README
+++ b/jquery/README
@@ -1,6 +1,6 @@
Doxygen's jquery.js script is composed of minified versions of the following
packages:
-- jquery 3.3.1: https://jquery.com/download/
+- jquery 3.4.1: https://jquery.com/download/
- jquery.ui 1.12.1: https://github.com/jquery/jquery-ui
modules required:
- jquery.ui.core all
@@ -12,3 +12,9 @@ packages:
- jquery.smartmenus: 1.1.0: https://www.smartmenus.org/
The Makefile will built the jquery.js files used by doxygen.
+
+Note that there is a performance issue in the default powertip version.
+See https://github.com/stevenbenner/jquery-powertip/issues/178
+Until that is fixed a modified version is shipped with doxygen. This version
+removes the "destroy" functionality which was not used by doxygen anyway.
+
diff --git a/jquery/jquery-3.3.1.min.js b/jquery/jquery-3.3.1.min.js
deleted file mode 100644
index 4d9b3a2..0000000
--- a/jquery/jquery-3.3.1.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
-!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
diff --git a/jquery/jquery-3.4.1.min.js b/jquery/jquery-3.4.1.min.js
new file mode 100644
index 0000000..a1c07fd
--- /dev/null
+++ b/jquery/jquery-3.4.1.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
diff --git a/jquery/jquery.powertip-1.3.1.min.js b/jquery/jquery.powertip-1.3.1.min.js
deleted file mode 100644
index 2e7383a..0000000
--- a/jquery/jquery.powertip-1.3.1.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*!
- PowerTip v1.3.1 (2018-04-15)
- https://stevenbenner.github.io/jquery-powertip/
- Copyright (c) 2018 Steven Benner (http://stevenbenner.com/).
- Released under MIT license.
- https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
-*/
-!function(e,t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(h){var v=h(document),n=h(window),e=h("body"),m="displayController",T="hasActiveHover",g="forcedOpen",i="hasMouseMove",y="mouseOnToPopup",a="originalTitle",b="powertip",H="powertipjq",k="powertiptarget",P=".powertip",O=180/Math.PI,t=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"],I={elements:null,tooltips:null,isTipOpen:!1,isFixedTipOpen:!1,isClosing:!1,tipOpenImminent:!1,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:!1,delayInProgress:!1,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0},l={none:0,top:1,bottom:2,left:4,right:8};function x(){var o=this;o.top="auto",o.left="auto",o.right="auto",o.bottom="auto",o.set=function(e,t){h.isNumeric(t)&&(o[e]=Math.round(t))}}function c(o,n,i){var s=null,t=null;function r(e,t){a(),o.data(T)?l():e?(t&&o.data(g,!0),c(),i.showTip(o)):(I.tipOpenImminent=!0,s=setTimeout(function(){var e,t;s=null,e=Math.abs(I.previousX-I.currentX),t=Math.abs(I.previousY-I.currentY),e+t<n.intentSensitivity?(l(),c(),i.showTip(o)):(I.previousX=I.currentX,I.previousY=I.currentY,r())},n.intentPollInterval))}function a(e){s=clearTimeout(s),(I.closeDelayTimeout&&t===I.closeDelayTimeout||e)&&l()}function l(){I.closeDelayTimeout=clearTimeout(I.closeDelayTimeout),I.delayInProgress=!1}function c(){I.delayInProgress&&I.activeHover&&!I.activeHover.is(o)&&I.activeHover.data(m).hide(!0)}this.show=r,this.hide=function(e){t&&(t=I.closeDelayTimeout=clearTimeout(t),I.delayInProgress=!1),a(),I.tipOpenImminent=!1,o.data(T)&&(o.data(g,!1),e?i.hideTip(o):(I.delayInProgress=!0,I.closeDelayTimeout=setTimeout(function(){I.closeDelayTimeout=null,i.hideTip(o),I.delayInProgress=!1,t=null},n.closeDelay),t=I.closeDelayTimeout))},this.cancel=a,this.resetPosition=function(){i.resetPosition(o)}}function o(){this.compute=function(e,t,o,n,i){var s,r,a=t.split("-")[0],l=new x;switch(r=e,s=Boolean(window.SVGElement&&r[0]instanceof SVGElement)?function(e,t){var o,n,i,s,r=e.closest("svg")[0],a=e[0],l=r.createSVGPoint(),c=a.getBBox(),u=a.getScreenCTM(),p=c.width/2,f=c.height/2,w=[],d=["nw","n","ne","e","se","s","sw","w"];function h(){w.push(l.matrixTransform(u))}if(l.x=c.x,l.y=c.y,h(),l.x+=p,h(),l.x+=p,h(),l.y+=f,h(),l.y+=f,h(),l.x-=p,h(),l.x-=p,h(),l.y-=f,h(),w[0].y!==w[1].y||w[0].x!==w[7].x)for(n=Math.atan2(u.b,u.a)*O,(i=Math.ceil((n%360-22.5)/45))<1&&(i+=8);i--;)d.push(d.shift());for(s=0;s<w.length;s++)if(d[s]===t){o=w[s];break}return{top:o.y+I.scrollTop,left:o.x+I.scrollLeft}}(e,a):function(e,t){var o,n,i=e.offset(),s=e.outerWidth(),r=e.outerHeight();switch(t){case"n":o=i.left+s/2,n=i.top;break;case"e":o=i.left+s,n=i.top+r/2;break;case"s":o=i.left+s/2,n=i.top+r;break;case"w":o=i.left,n=i.top+r/2;break;case"nw":o=i.left,n=i.top;break;case"ne":o=i.left+s,n=i.top;break;case"sw":o=i.left,n=i.top+r;break;case"se":o=i.left+s,n=i.top+r}return{top:n,left:o}}(e,a),t){case"n":l.set("left",s.left-o/2),l.set("bottom",I.windowHeight-s.top+i);break;case"e":l.set("left",s.left+i),l.set("top",s.top-n/2);break;case"s":l.set("left",s.left-o/2),l.set("top",s.top+i);break;case"w":l.set("top",s.top-n/2),l.set("right",I.windowWidth-s.left+i);break;case"nw":l.set("bottom",I.windowHeight-s.top+i),l.set("right",I.windowWidth-s.left-20);break;case"nw-alt":l.set("left",s.left),l.set("bottom",I.windowHeight-s.top+i);break;case"ne":l.set("left",s.left-20),l.set("bottom",I.windowHeight-s.top+i);break;case"ne-alt":l.set("bottom",I.windowHeight-s.top+i),l.set("right",I.windowWidth-s.left);break;case"sw":l.set("top",s.top+i),l.set("right",I.windowWidth-s.left-20);break;case"sw-alt":l.set("left",s.left),l.set("top",s.top+i);break;case"se":l.set("left",s.left-20),l.set("top",s.top+i);break;case"se-alt":l.set("top",s.top+i),l.set("right",I.windowWidth-s.left)}return l}}function u(c){var r=new o,u=h("#"+c.popupId);function p(t){I.isClosing=!0,I.isTipOpen=!1,I.desyncTimeout=clearInterval(I.desyncTimeout),t.data(T,!1),t.data(g,!1),v.off("click"+P),u.off(P),u.fadeOut(c.fadeOutTime,function(){var e=new x;I.activeHover=null,I.isClosing=!1,I.isFixedTipOpen=!1,u.removeClass(),e.set("top",I.currentY+c.offset),e.set("left",I.currentX+c.offset),u.css(e),t.trigger("powerTipClose")})}function f(){var e,t,o,n;!I.isFixedTipOpen&&(I.isTipOpen||I.tipOpenImminent&&u.data(i))&&(e=u.outerWidth(),t=u.outerHeight(),(o=new x).set("top",I.currentY+c.offset),o.set("left",I.currentX+c.offset),(n=M(o,e,t))!==l.none&&(1===function(e){var t=0;for(;e;)e&=e-1,t++;return t}(n)?n===l.right?o.set("left",I.scrollLeft+I.windowWidth-e):n===l.bottom&&o.set("top",I.scrollTop+I.windowHeight-t):(o.set("left",I.currentX-e-c.offset),o.set("top",I.currentY-t-c.offset))),u.css(o))}function w(n){var e,i;c.smartPlacement||c.followMouse&&n.data(g)?(e=h.fn.powerTip.smartPlacementLists[c.placement],h.each(e,function(e,t){var o=M(s(n,t),u.outerWidth(),u.outerHeight());return i=t,o!==l.none})):(s(n,c.placement),i=c.placement),u.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt"),u.addClass(i)}function s(e,t){var o,n,i=0,s=new x;for(s.set("top",0),s.set("left",0),u.css(s);o=u.outerWidth(),n=u.outerHeight(),s=r.compute(e,t,o,n,c.offset),u.css(s),++i<=5&&(o!==u.outerWidth()||n!==u.outerHeight()););return s}function d(){var e=!1,t=0<h.grep(["mouseleave","mouseout","blur","focusout"],function(e){return-1!==h.inArray(e,c.closeEvents)}).length;I.isTipOpen&&!I.isClosing&&!I.delayInProgress&&t&&(!1===I.activeHover.data(T)||I.activeHover.is(":disabled")?e=!0:X(I.activeHover)||I.activeHover.is(":focus")||I.activeHover.data(g)||u.data(y)&&X(u)||(e=!0),e&&p(I.activeHover))}0===u.length&&(u=h("<div/>",{id:c.popupId}),0===e.length&&(e=h("body")),e.append(u),I.tooltips=I.tooltips?I.tooltips.add(u):u),c.followMouse&&(u.data(i)||(v.on("mousemove"+P,f),n.on("scroll"+P,f),u.data(i,!0))),this.showTip=function(o){o.data(T,!0),u.queue(function(e){!function t(o){var e;if(o.data(T)){if(I.isTipOpen)return I.isClosing||p(I.activeHover),void u.delay(100).queue(function(e){t(o),e()});var n,i,s,r,a,l;o.trigger("powerTipPreRender"),r=(n=o).data(b),a=n.data(H),l=n.data(k),r?(h.isFunction(r)&&(r=r.call(n[0])),s=r):a?(h.isFunction(a)&&(a=a.call(n[0])),0<a.length&&(s=a.clone(!0,!0))):l&&0<(i=h("#"+l)).length&&(s=i.html()),(e=s)&&(u.empty().append(e),o.trigger("powerTipRender"),I.activeHover=o,I.isTipOpen=!0,u.data(y,c.mouseOnToPopup),u.addClass(c.popupClass),!c.followMouse||o.data(g)?(w(o),I.isFixedTipOpen=!0):f(),o.data(g)||c.followMouse||v.on("click"+P,function(e){var t=e.target;t!==o[0]&&(c.mouseOnToPopup&&(t===u[0]||h.contains(u[0],t))||h.powerTip.hide())}),c.mouseOnToPopup&&!c.manual&&(u.on("mouseenter"+P,function(){I.activeHover&&I.activeHover.data(m).cancel()}),u.on("mouseleave"+P,function(){I.activeHover&&I.activeHover.data(m).hide()})),u.fadeIn(c.fadeInTime,function(){I.desyncTimeout||(I.desyncTimeout=setInterval(d,500)),o.trigger("powerTipOpen")}))}}(o),e()})},this.hideTip=p,this.resetPosition=w}function p(e){return Boolean(e&&-1<h.inArray(e.type,t)&&"number"==typeof e.pageX)}function f(){I.scrollLeft=n.scrollLeft(),I.scrollTop=n.scrollTop(),I.windowWidth=n.width(),I.windowHeight=n.height()}function w(){I.windowWidth=n.width(),I.windowHeight=n.height()}function d(){var e=n.scrollLeft(),t=n.scrollTop();e!==I.scrollLeft&&(I.currentX+=e-I.scrollLeft,I.scrollLeft=e),t!==I.scrollTop&&(I.currentY+=t-I.scrollTop,I.scrollTop=t)}function C(e){I.currentX=e.pageX,I.currentY=e.pageY}function X(e){var t=e.offset(),o=e[0].getBoundingClientRect(),n=o.right-o.left,i=o.bottom-o.top;return I.currentX>=t.left&&I.currentX<=t.left+n&&I.currentY>=t.top&&I.currentY<=t.top+i}function M(e,t,o){var n=I.scrollTop,i=I.scrollLeft,s=n+I.windowHeight,r=i+I.windowWidth,a=l.none;return(e.top<n||Math.abs(e.bottom-I.windowHeight)-o<n)&&(a|=l.top),(e.top+o>s||Math.abs(e.bottom-I.windowHeight)>s)&&(a|=l.bottom),(e.left<i||e.right+t>r)&&(a|=l.left),(e.left+t>r||e.right<i)&&(a|=l.right),a}return h.fn.powerTip=function(e,t){var s,r,o=this;return o.length?"string"===h.type(e)&&h.powerTip[e]?h.powerTip[e].call(o,o,t):(s=h.extend({},h.fn.powerTip.defaults,e),h.powerTip.destroy(o),r=new u(s),I.mouseTrackingActive||(I.mouseTrackingActive=!0,f(),h(f),v.on("mousemove"+P,C),n.on("resize"+P,w),n.on("scroll"+P,d)),o.each(function(){var e=h(this),t=e.data(b),o=e.data(H),n=e.data(k),i=e.attr("title");t||n||o||!i||(e.data(b,i),e.data(a,i),e.removeAttr("title")),e.data(m,new c(e,s,r))}),s.manual||(h.each(s.openEvents,function(e,t){-1<h.inArray(t,s.closeEvents)?o.on(t+P,function(e){h.powerTip.toggle(this,e)}):o.on(t+P,function(e){h.powerTip.show(this,e)})}),h.each(s.closeEvents,function(e,t){h.inArray(t,s.openEvents)<0&&o.on(t+P,function(e){h.powerTip.hide(this,!p(e))})}),o.on("keydown"+P,function(e){27===e.keyCode&&h.powerTip.hide(this,!0)})),I.elements=I.elements?I.elements.add(o):o,o):o},h.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:!1,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:!1,offset:10,mouseOnToPopup:!1,manual:!1,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]},h.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]},h.powerTip={show:function(e,t){return p(t)?(C(t),I.previousX=t.pageX,I.previousY=t.pageY,h(e).data(m).show()):h(e).first().data(m).show(!0,!0),e},reposition:function(e){return h(e).first().data(m).resetPosition(),e},hide:function(e,t){var o;return t=!e||t,e?o=h(e).first().data(m):I.activeHover&&(o=I.activeHover.data(m)),o&&o.hide(t),e},toggle:function(e,t){return I.activeHover&&I.activeHover.is(e)?h.powerTip.hide(e,!p(t)):h.powerTip.show(e,t),e},destroy:function(e){var t=e?h(e):I.elements;return I.elements&&0!==I.elements.length&&(I.isTipOpen&&!I.isClosing&&0<t.filter(I.activeHover).length&&(I.delayInProgress&&I.activeHover.data(m).cancel(),h.powerTip.hide(I.activeHover,!0)),t.off(P).each(function(){var e=h(this),t=[a,m,T,g];e.data(a)&&(e.attr("title",e.data(a)),t.push(b)),e.removeData(t)}),I.elements=I.elements.not(t),0===I.elements.length&&(n.off(P),v.off(P),I.mouseTrackingActive=!1,I.tooltips.remove(),I.tooltips=null)),e}},h.powerTip.showTip=h.powerTip.show,h.powerTip.closeTip=h.powerTip.hide,h.powerTip}); \ No newline at end of file
diff --git a/jquery/jquery.powertip-1.3.1.mod.js b/jquery/jquery.powertip-1.3.1.mod.js
new file mode 100644
index 0000000..197599c
--- /dev/null
+++ b/jquery/jquery.powertip-1.3.1.mod.js
@@ -0,0 +1,1324 @@
+/*!
+ PowerTip v1.3.1 (2018-04-15)
+ https://stevenbenner.github.io/jquery-powertip/
+ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(root, factory) {
+ // support loading the plugin via common patterns
+ if (typeof define === 'function' && define.amd) {
+ // load the plugin as an amd module
+ define([ 'jquery' ], factory);
+ } else if (typeof module === 'object' && module.exports) {
+ // load the plugin as a commonjs module
+ module.exports = factory(require('jquery'));
+ } else {
+ // load the plugin as a global
+ factory(root.jQuery);
+ }
+}(this, function($) {
+ // useful private variables
+ var $document = $(document),
+ $window = $(window),
+ $body = $('body');
+
+ // constants
+ var DATA_DISPLAYCONTROLLER = 'displayController',
+ DATA_HASACTIVEHOVER = 'hasActiveHover',
+ DATA_FORCEDOPEN = 'forcedOpen',
+ DATA_HASMOUSEMOVE = 'hasMouseMove',
+ DATA_MOUSEONTOTIP = 'mouseOnToPopup',
+ DATA_ORIGINALTITLE = 'originalTitle',
+ DATA_POWERTIP = 'powertip',
+ DATA_POWERTIPJQ = 'powertipjq',
+ DATA_POWERTIPTARGET = 'powertiptarget',
+ EVENT_NAMESPACE = '.powertip',
+ RAD2DEG = 180 / Math.PI,
+ MOUSE_EVENTS = [
+ 'click',
+ 'dblclick',
+ 'mousedown',
+ 'mouseup',
+ 'mousemove',
+ 'mouseover',
+ 'mouseout',
+ 'mouseenter',
+ 'mouseleave',
+ 'contextmenu'
+ ];
+
+ /**
+ * Session data
+ * Private properties global to all powerTip instances
+ */
+ var session = {
+ tooltips: null,
+ isTipOpen: false,
+ isFixedTipOpen: false,
+ isClosing: false,
+ tipOpenImminent: false,
+ activeHover: null,
+ currentX: 0,
+ currentY: 0,
+ previousX: 0,
+ previousY: 0,
+ desyncTimeout: null,
+ closeDelayTimeout: null,
+ mouseTrackingActive: false,
+ delayInProgress: false,
+ windowWidth: 0,
+ windowHeight: 0,
+ scrollTop: 0,
+ scrollLeft: 0
+ };
+
+ /**
+ * Collision enumeration
+ * @enum {number}
+ */
+ var Collision = {
+ none: 0,
+ top: 1,
+ bottom: 2,
+ left: 4,
+ right: 8
+ };
+
+ /**
+ * Display hover tooltips on the matched elements.
+ * @param {(Object|string)=} opts The options object to use for the plugin, or
+ * the name of a method to invoke on the first matched element.
+ * @param {*=} [arg] Argument for an invoked method (optional).
+ * @return {jQuery} jQuery object for the matched selectors.
+ */
+ $.fn.powerTip = function(opts, arg) {
+ var targetElements = this,
+ options,
+ tipController;
+
+ // don't do any work if there were no matched elements
+ if (!targetElements.length) {
+ return targetElements;
+ }
+
+ // handle api method calls on the plugin, e.g. powerTip('hide')
+ if ($.type(opts) === 'string' && $.powerTip[opts]) {
+ return $.powerTip[opts].call(targetElements, targetElements, arg);
+ }
+
+ // extend options
+ options = $.extend({}, $.fn.powerTip.defaults, opts);
+
+ // instantiate the TooltipController for this instance
+ tipController = new TooltipController(options);
+
+ // hook mouse and viewport dimension tracking
+ initTracking();
+
+ // setup the elements
+ targetElements.each(function elementSetup() {
+ var $this = $(this),
+ dataPowertip = $this.data(DATA_POWERTIP),
+ dataElem = $this.data(DATA_POWERTIPJQ),
+ dataTarget = $this.data(DATA_POWERTIPTARGET),
+ title = $this.attr('title');
+
+ // attempt to use title attribute text if there is no data-powertip,
+ // data-powertipjq or data-powertiptarget. If we do use the title
+ // attribute, delete the attribute so the browser will not show it
+ if (!dataPowertip && !dataTarget && !dataElem && title) {
+ $this.data(DATA_POWERTIP, title);
+ $this.data(DATA_ORIGINALTITLE, title);
+ $this.removeAttr('title');
+ }
+
+ // create hover controllers for each element
+ $this.data(
+ DATA_DISPLAYCONTROLLER,
+ new DisplayController($this, options, tipController)
+ );
+ });
+
+ // attach events to matched elements if the manual option is not enabled
+ if (!options.manual) {
+ // attach open events
+ $.each(options.openEvents, function(idx, evt) {
+ if ($.inArray(evt, options.closeEvents) > -1) {
+ // event is in both openEvents and closeEvents, so toggle it
+ targetElements.on(evt + EVENT_NAMESPACE, function elementToggle(event) {
+ $.powerTip.toggle(this, event);
+ });
+ } else {
+ targetElements.on(evt + EVENT_NAMESPACE, function elementOpen(event) {
+ $.powerTip.show(this, event);
+ });
+ }
+ });
+
+ // attach close events
+ $.each(options.closeEvents, function(idx, evt) {
+ if ($.inArray(evt, options.openEvents) < 0) {
+ targetElements.on(evt + EVENT_NAMESPACE, function elementClose(event) {
+ // set immediate to true for any event without mouse info
+ $.powerTip.hide(this, !isMouseEvent(event));
+ });
+ }
+ });
+
+ // attach escape key close event
+ targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) {
+ // always close tooltip when the escape key is pressed
+ if (event.keyCode === 27) {
+ $.powerTip.hide(this, true);
+ }
+ });
+ }
+
+ return targetElements;
+ };
+
+ /**
+ * Default options for the powerTip plugin.
+ */
+ $.fn.powerTip.defaults = {
+ fadeInTime: 200,
+ fadeOutTime: 100,
+ followMouse: false,
+ popupId: 'powerTip',
+ popupClass: null,
+ intentSensitivity: 7,
+ intentPollInterval: 100,
+ closeDelay: 100,
+ placement: 'n',
+ smartPlacement: false,
+ offset: 10,
+ mouseOnToPopup: false,
+ manual: false,
+ openEvents: [ 'mouseenter', 'focus' ],
+ closeEvents: [ 'mouseleave', 'blur' ]
+ };
+
+ /**
+ * Default smart placement priority lists.
+ * The first item in the array is the highest priority, the last is the lowest.
+ * The last item is also the default, which will be used if all previous options
+ * do not fit.
+ */
+ $.fn.powerTip.smartPlacementLists = {
+ n: [ 'n', 'ne', 'nw', 's' ],
+ e: [ 'e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e' ],
+ s: [ 's', 'se', 'sw', 'n' ],
+ w: [ 'w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w' ],
+ nw: [ 'nw', 'w', 'sw', 'n', 's', 'se', 'nw' ],
+ ne: [ 'ne', 'e', 'se', 'n', 's', 'sw', 'ne' ],
+ sw: [ 'sw', 'w', 'nw', 's', 'n', 'ne', 'sw' ],
+ se: [ 'se', 'e', 'ne', 's', 'n', 'nw', 'se' ],
+ 'nw-alt': [ 'nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e' ],
+ 'ne-alt': [ 'ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w' ],
+ 'sw-alt': [ 'sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e' ],
+ 'se-alt': [ 'se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w' ]
+ };
+
+ /**
+ * Public API
+ */
+ $.powerTip = {
+ /**
+ * Attempts to show the tooltip for the specified element.
+ * @param {jQuery|Element} element The element to open the tooltip for.
+ * @param {jQuery.Event=} event jQuery event for hover intent and mouse
+ * tracking (optional).
+ * @return {jQuery|Element} The original jQuery object or DOM Element.
+ */
+ show: function apiShowTip(element, event) {
+ // if we were given a mouse event then run the hover intent testing,
+ // otherwise, simply show the tooltip asap
+ if (isMouseEvent(event)) {
+ trackMouse(event);
+ session.previousX = event.pageX;
+ session.previousY = event.pageY;
+ $(element).data(DATA_DISPLAYCONTROLLER).show();
+ } else {
+ $(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true);
+ }
+ return element;
+ },
+
+ /**
+ * Repositions the tooltip on the element.
+ * @param {jQuery|Element} element The element the tooltip is shown for.
+ * @return {jQuery|Element} The original jQuery object or DOM Element.
+ */
+ reposition: function apiResetPosition(element) {
+ $(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();
+ return element;
+ },
+
+ /**
+ * Attempts to close any open tooltips.
+ * @param {(jQuery|Element)=} element The element with the tooltip that
+ * should be closed (optional).
+ * @param {boolean=} immediate Disable close delay (optional).
+ * @return {jQuery|Element|undefined} The original jQuery object or DOM
+ * Element, if one was specified.
+ */
+ hide: function apiCloseTip(element, immediate) {
+ var displayController;
+
+ // set immediate to true when no element is specified
+ immediate = element ? immediate : true;
+
+ // find the relevant display controller
+ if (element) {
+ displayController = $(element).first().data(DATA_DISPLAYCONTROLLER);
+ } else if (session.activeHover) {
+ displayController = session.activeHover.data(DATA_DISPLAYCONTROLLER);
+ }
+
+ // if found, hide the tip
+ if (displayController) {
+ displayController.hide(immediate);
+ }
+
+ return element;
+ },
+
+ /**
+ * Toggles the tooltip for the specified element. This will open a closed
+ * tooltip, or close an open tooltip.
+ * @param {jQuery|Element} element The element with the tooltip that
+ * should be toggled.
+ * @param {jQuery.Event=} event jQuery event for hover intent and mouse
+ * tracking (optional).
+ * @return {jQuery|Element} The original jQuery object or DOM Element.
+ */
+ toggle: function apiToggle(element, event) {
+ if (session.activeHover && session.activeHover.is(element)) {
+ // tooltip for element is active, so close it
+ $.powerTip.hide(element, !isMouseEvent(event));
+ } else {
+ // tooltip for element is not active, so open it
+ $.powerTip.show(element, event);
+ }
+ return element;
+ },
+
+ };
+
+ // API aliasing
+ $.powerTip.showTip = $.powerTip.show;
+ $.powerTip.closeTip = $.powerTip.hide;
+
+ /**
+ * Creates a new CSSCoordinates object.
+ * @private
+ * @constructor
+ */
+ function CSSCoordinates() {
+ var me = this;
+
+ // initialize object properties
+ me.top = 'auto';
+ me.left = 'auto';
+ me.right = 'auto';
+ me.bottom = 'auto';
+
+ /**
+ * Set a property to a value.
+ * @private
+ * @param {string} property The name of the property.
+ * @param {number} value The value of the property.
+ */
+ me.set = function(property, value) {
+ if ($.isNumeric(value)) {
+ me[property] = Math.round(value);
+ }
+ };
+ }
+
+ /**
+ * Creates a new tooltip display controller.
+ * @private
+ * @constructor
+ * @param {jQuery} element The element that this controller will handle.
+ * @param {Object} options Options object containing settings.
+ * @param {TooltipController} tipController The TooltipController object for
+ * this instance.
+ */
+ function DisplayController(element, options, tipController) {
+ var hoverTimer = null,
+ myCloseDelay = null;
+
+ /**
+ * Begins the process of showing a tooltip.
+ * @private
+ * @param {boolean=} immediate Skip intent testing (optional).
+ * @param {boolean=} forceOpen Ignore cursor position and force tooltip to
+ * open (optional).
+ */
+ function openTooltip(immediate, forceOpen) {
+ cancelTimer();
+ if (!element.data(DATA_HASACTIVEHOVER)) {
+ if (!immediate) {
+ session.tipOpenImminent = true;
+ hoverTimer = setTimeout(
+ function intentDelay() {
+ hoverTimer = null;
+ checkForIntent();
+ },
+ options.intentPollInterval
+ );
+ } else {
+ if (forceOpen) {
+ element.data(DATA_FORCEDOPEN, true);
+ }
+ closeAnyDelayed();
+ tipController.showTip(element);
+ }
+ } else {
+ // cursor left and returned to this element, cancel close
+ cancelClose();
+ }
+ }
+
+ /**
+ * Begins the process of closing a tooltip.
+ * @private
+ * @param {boolean=} disableDelay Disable close delay (optional).
+ */
+ function closeTooltip(disableDelay) {
+ // if this instance already has a close delay in progress then halt it
+ if (myCloseDelay) {
+ myCloseDelay = session.closeDelayTimeout = clearTimeout(myCloseDelay);
+ session.delayInProgress = false;
+ }
+ cancelTimer();
+ session.tipOpenImminent = false;
+ if (element.data(DATA_HASACTIVEHOVER)) {
+ element.data(DATA_FORCEDOPEN, false);
+ if (!disableDelay) {
+ session.delayInProgress = true;
+ session.closeDelayTimeout = setTimeout(
+ function closeDelay() {
+ session.closeDelayTimeout = null;
+ tipController.hideTip(element);
+ session.delayInProgress = false;
+ myCloseDelay = null;
+ },
+ options.closeDelay
+ );
+ // save internal reference close delay id so we can check if the
+ // active close delay belongs to this instance
+ myCloseDelay = session.closeDelayTimeout;
+ } else {
+ tipController.hideTip(element);
+ }
+ }
+ }
+
+ /**
+ * Checks mouse position to make sure that the user intended to hover on the
+ * specified element before showing the tooltip.
+ * @private
+ */
+ function checkForIntent() {
+ // calculate mouse position difference
+ var xDifference = Math.abs(session.previousX - session.currentX),
+ yDifference = Math.abs(session.previousY - session.currentY),
+ totalDifference = xDifference + yDifference;
+
+ // check if difference has passed the sensitivity threshold
+ if (totalDifference < options.intentSensitivity) {
+ cancelClose();
+ closeAnyDelayed();
+ tipController.showTip(element);
+ } else {
+ // try again
+ session.previousX = session.currentX;
+ session.previousY = session.currentY;
+ openTooltip();
+ }
+ }
+
+ /**
+ * Cancels active hover timer.
+ * @private
+ * @param {boolean=} stopClose Cancel any active close delay timer.
+ */
+ function cancelTimer(stopClose) {
+ hoverTimer = clearTimeout(hoverTimer);
+ // cancel the current close delay if the active close delay is for this
+ // element or the stopClose argument is true
+ if (session.closeDelayTimeout && myCloseDelay === session.closeDelayTimeout || stopClose) {
+ cancelClose();
+ }
+ }
+
+ /**
+ * Cancels any active close delay timer.
+ * @private
+ */
+ function cancelClose() {
+ session.closeDelayTimeout = clearTimeout(session.closeDelayTimeout);
+ session.delayInProgress = false;
+ }
+
+ /**
+ * Asks any tooltips waiting on their close delay to close now.
+ * @private
+ */
+ function closeAnyDelayed() {
+ // if another element is waiting for its close delay then we should ask
+ // it to close immediately so we can proceed without unexpected timeout
+ // code being run during this tooltip's lifecycle
+ if (session.delayInProgress && session.activeHover && !session.activeHover.is(element)) {
+ session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true);
+ }
+ }
+
+ /**
+ * Repositions the tooltip on this element.
+ * @private
+ */
+ function repositionTooltip() {
+ tipController.resetPosition(element);
+ }
+
+ // expose the methods
+ this.show = openTooltip;
+ this.hide = closeTooltip;
+ this.cancel = cancelTimer;
+ this.resetPosition = repositionTooltip;
+ }
+
+ /**
+ * Creates a new Placement Calculator.
+ * @private
+ * @constructor
+ */
+ function PlacementCalculator() {
+ /**
+ * Compute the CSS position to display a tooltip at the specified placement
+ * relative to the specified element.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ * @param {string} placement The placement for the tooltip.
+ * @param {number} tipWidth Width of the tooltip element in pixels.
+ * @param {number} tipHeight Height of the tooltip element in pixels.
+ * @param {number} offset Distance to offset tooltips in pixels.
+ * @return {CSSCoordinates} A CSSCoordinates object with the position.
+ */
+ function computePlacementCoords(element, placement, tipWidth, tipHeight, offset) {
+ var placementBase = placement.split('-')[0], // ignore 'alt' for corners
+ coords = new CSSCoordinates(),
+ position;
+
+ if (isSvgElement(element)) {
+ position = getSvgPlacement(element, placementBase);
+ } else {
+ position = getHtmlPlacement(element, placementBase);
+ }
+
+ // calculate the appropriate x and y position in the document
+ switch (placement) {
+ case 'n':
+ coords.set('left', position.left - (tipWidth / 2));
+ coords.set('bottom', session.windowHeight - position.top + offset);
+ break;
+ case 'e':
+ coords.set('left', position.left + offset);
+ coords.set('top', position.top - (tipHeight / 2));
+ break;
+ case 's':
+ coords.set('left', position.left - (tipWidth / 2));
+ coords.set('top', position.top + offset);
+ break;
+ case 'w':
+ coords.set('top', position.top - (tipHeight / 2));
+ coords.set('right', session.windowWidth - position.left + offset);
+ break;
+ case 'nw':
+ coords.set('bottom', session.windowHeight - position.top + offset);
+ coords.set('right', session.windowWidth - position.left - 20);
+ break;
+ case 'nw-alt':
+ coords.set('left', position.left);
+ coords.set('bottom', session.windowHeight - position.top + offset);
+ break;
+ case 'ne':
+ coords.set('left', position.left - 20);
+ coords.set('bottom', session.windowHeight - position.top + offset);
+ break;
+ case 'ne-alt':
+ coords.set('bottom', session.windowHeight - position.top + offset);
+ coords.set('right', session.windowWidth - position.left);
+ break;
+ case 'sw':
+ coords.set('top', position.top + offset);
+ coords.set('right', session.windowWidth - position.left - 20);
+ break;
+ case 'sw-alt':
+ coords.set('left', position.left);
+ coords.set('top', position.top + offset);
+ break;
+ case 'se':
+ coords.set('left', position.left - 20);
+ coords.set('top', position.top + offset);
+ break;
+ case 'se-alt':
+ coords.set('top', position.top + offset);
+ coords.set('right', session.windowWidth - position.left);
+ break;
+ }
+
+ return coords;
+ }
+
+ /**
+ * Finds the tooltip attachment point in the document for a HTML DOM element
+ * for the specified placement.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ * @param {string} placement The placement for the tooltip.
+ * @return {Object} An object with the top,left position values.
+ */
+ function getHtmlPlacement(element, placement) {
+ var objectOffset = element.offset(),
+ objectWidth = element.outerWidth(),
+ objectHeight = element.outerHeight(),
+ left,
+ top;
+
+ // calculate the appropriate x and y position in the document
+ switch (placement) {
+ case 'n':
+ left = objectOffset.left + objectWidth / 2;
+ top = objectOffset.top;
+ break;
+ case 'e':
+ left = objectOffset.left + objectWidth;
+ top = objectOffset.top + objectHeight / 2;
+ break;
+ case 's':
+ left = objectOffset.left + objectWidth / 2;
+ top = objectOffset.top + objectHeight;
+ break;
+ case 'w':
+ left = objectOffset.left;
+ top = objectOffset.top + objectHeight / 2;
+ break;
+ case 'nw':
+ left = objectOffset.left;
+ top = objectOffset.top;
+ break;
+ case 'ne':
+ left = objectOffset.left + objectWidth;
+ top = objectOffset.top;
+ break;
+ case 'sw':
+ left = objectOffset.left;
+ top = objectOffset.top + objectHeight;
+ break;
+ case 'se':
+ left = objectOffset.left + objectWidth;
+ top = objectOffset.top + objectHeight;
+ break;
+ }
+
+ return {
+ top: top,
+ left: left
+ };
+ }
+
+ /**
+ * Finds the tooltip attachment point in the document for a SVG element for
+ * the specified placement.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ * @param {string} placement The placement for the tooltip.
+ * @return {Object} An object with the top,left position values.
+ */
+ function getSvgPlacement(element, placement) {
+ var svgElement = element.closest('svg')[0],
+ domElement = element[0],
+ point = svgElement.createSVGPoint(),
+ boundingBox = domElement.getBBox(),
+ matrix = domElement.getScreenCTM(),
+ halfWidth = boundingBox.width / 2,
+ halfHeight = boundingBox.height / 2,
+ placements = [],
+ placementKeys = [ 'nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w' ],
+ coords,
+ rotation,
+ steps,
+ x;
+
+ /**
+ * Transform and append the current points to the placements list.
+ * @private
+ */
+ function pushPlacement() {
+ placements.push(point.matrixTransform(matrix));
+ }
+
+ // get bounding box corners and midpoints
+ point.x = boundingBox.x;
+ point.y = boundingBox.y;
+ pushPlacement();
+ point.x += halfWidth;
+ pushPlacement();
+ point.x += halfWidth;
+ pushPlacement();
+ point.y += halfHeight;
+ pushPlacement();
+ point.y += halfHeight;
+ pushPlacement();
+ point.x -= halfWidth;
+ pushPlacement();
+ point.x -= halfWidth;
+ pushPlacement();
+ point.y -= halfHeight;
+ pushPlacement();
+
+ // determine rotation
+ if (placements[0].y !== placements[1].y || placements[0].x !== placements[7].x) {
+ rotation = Math.atan2(matrix.b, matrix.a) * RAD2DEG;
+ steps = Math.ceil(((rotation % 360) - 22.5) / 45);
+ if (steps < 1) {
+ steps += 8;
+ }
+ while (steps--) {
+ placementKeys.push(placementKeys.shift());
+ }
+ }
+
+ // find placement
+ for (x = 0; x < placements.length; x++) {
+ if (placementKeys[x] === placement) {
+ coords = placements[x];
+ break;
+ }
+ }
+
+ return {
+ top: coords.y + session.scrollTop,
+ left: coords.x + session.scrollLeft
+ };
+ }
+
+ // expose methods
+ this.compute = computePlacementCoords;
+ }
+
+ /**
+ * Creates a new tooltip controller.
+ * @private
+ * @constructor
+ * @param {Object} options Options object containing settings.
+ */
+ function TooltipController(options) {
+ var placementCalculator = new PlacementCalculator(),
+ tipElement = $('#' + options.popupId);
+
+ // build and append tooltip div if it does not already exist
+ if (tipElement.length === 0) {
+ tipElement = $('<div/>', { id: options.popupId });
+ // grab body element if it was not populated when the script loaded
+ // note: this hack exists solely for jsfiddle support
+ if ($body.length === 0) {
+ $body = $('body');
+ }
+ $body.append(tipElement);
+ // remember the tooltip elements that the plugin has created
+ session.tooltips = session.tooltips ? session.tooltips.add(tipElement) : tipElement;
+ }
+
+ // hook mousemove for cursor follow tooltips
+ if (options.followMouse) {
+ // only one positionTipOnCursor hook per tooltip element, please
+ if (!tipElement.data(DATA_HASMOUSEMOVE)) {
+ $document.on('mousemove' + EVENT_NAMESPACE, positionTipOnCursor);
+ $window.on('scroll' + EVENT_NAMESPACE, positionTipOnCursor);
+ tipElement.data(DATA_HASMOUSEMOVE, true);
+ }
+ }
+
+ /**
+ * Gives the specified element the active-hover state and queues up the
+ * showTip function.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ */
+ function beginShowTip(element) {
+ element.data(DATA_HASACTIVEHOVER, true);
+ // show tooltip, asap
+ tipElement.queue(function queueTipInit(next) {
+ showTip(element);
+ next();
+ });
+ }
+
+ /**
+ * Shows the tooltip, as soon as possible.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ */
+ function showTip(element) {
+ var tipContent;
+
+ // it is possible, especially with keyboard navigation, to move on to
+ // another element with a tooltip during the queue to get to this point
+ // in the code. if that happens then we need to not proceed or we may
+ // have the fadeout callback for the last tooltip execute immediately
+ // after this code runs, causing bugs.
+ if (!element.data(DATA_HASACTIVEHOVER)) {
+ return;
+ }
+
+ // if the tooltip is open and we got asked to open another one then the
+ // old one is still in its fadeOut cycle, so wait and try again
+ if (session.isTipOpen) {
+ if (!session.isClosing) {
+ hideTip(session.activeHover);
+ }
+ tipElement.delay(100).queue(function queueTipAgain(next) {
+ showTip(element);
+ next();
+ });
+ return;
+ }
+
+ // trigger powerTipPreRender event
+ element.trigger('powerTipPreRender');
+
+ // set tooltip content
+ tipContent = getTooltipContent(element);
+ if (tipContent) {
+ tipElement.empty().append(tipContent);
+ } else {
+ // we have no content to display, give up
+ return;
+ }
+
+ // trigger powerTipRender event
+ element.trigger('powerTipRender');
+
+ session.activeHover = element;
+ session.isTipOpen = true;
+
+ tipElement.data(DATA_MOUSEONTOTIP, options.mouseOnToPopup);
+
+ // add custom class to tooltip element
+ tipElement.addClass(options.popupClass);
+
+ // set tooltip position
+ // revert to static placement when the "force open" flag was set because
+ // that flag means that we do not have accurate mouse position info
+ if (!options.followMouse || element.data(DATA_FORCEDOPEN)) {
+ positionTipOnElement(element);
+ session.isFixedTipOpen = true;
+ } else {
+ positionTipOnCursor();
+ }
+
+ // close tooltip when clicking anywhere on the page, with the exception
+ // of the tooltip's trigger element and any elements that are within a
+ // tooltip that has 'mouseOnToPopup' option enabled
+ // always enable this feature when the "force open" flag is set on a
+ // followMouse tooltip because we reverted to static placement above
+ if (!element.data(DATA_FORCEDOPEN) && !options.followMouse) {
+ $document.on('click' + EVENT_NAMESPACE, function documentClick(event) {
+ var target = event.target;
+ if (target !== element[0]) {
+ if (options.mouseOnToPopup) {
+ if (target !== tipElement[0] && !$.contains(tipElement[0], target)) {
+ $.powerTip.hide();
+ }
+ } else {
+ $.powerTip.hide();
+ }
+ }
+ });
+ }
+
+ // if we want to be able to mouse on to the tooltip then we need to
+ // attach hover events to the tooltip that will cancel a close request
+ // on mouseenter and start a new close request on mouseleave
+ // only hook these listeners if we're not in manual mode
+ if (options.mouseOnToPopup && !options.manual) {
+ tipElement.on('mouseenter' + EVENT_NAMESPACE, function tipMouseEnter() {
+ // check activeHover in case the mouse cursor entered the
+ // tooltip during the fadeOut and close cycle
+ if (session.activeHover) {
+ session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel();
+ }
+ });
+ tipElement.on('mouseleave' + EVENT_NAMESPACE, function tipMouseLeave() {
+ // check activeHover in case the mouse cursor left the tooltip
+ // during the fadeOut and close cycle
+ if (session.activeHover) {
+ session.activeHover.data(DATA_DISPLAYCONTROLLER).hide();
+ }
+ });
+ }
+
+ // fadein
+ tipElement.fadeIn(options.fadeInTime, function fadeInCallback() {
+ // start desync polling
+ if (!session.desyncTimeout) {
+ session.desyncTimeout = setInterval(closeDesyncedTip, 500);
+ }
+
+ // trigger powerTipOpen event
+ element.trigger('powerTipOpen');
+ });
+ }
+
+ /**
+ * Hides the tooltip.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ */
+ function hideTip(element) {
+ // reset session
+ session.isClosing = true;
+ session.isTipOpen = false;
+
+ // stop desync polling
+ session.desyncTimeout = clearInterval(session.desyncTimeout);
+
+ // reset element state
+ element.data(DATA_HASACTIVEHOVER, false);
+ element.data(DATA_FORCEDOPEN, false);
+
+ // remove document click handler
+ $document.off('click' + EVENT_NAMESPACE);
+
+ // unbind the mouseOnToPopup events if they were set
+ tipElement.off(EVENT_NAMESPACE);
+
+ // fade out
+ tipElement.fadeOut(options.fadeOutTime, function fadeOutCallback() {
+ var coords = new CSSCoordinates();
+
+ // reset session and tooltip element
+ session.activeHover = null;
+ session.isClosing = false;
+ session.isFixedTipOpen = false;
+ tipElement.removeClass();
+
+ // support mouse-follow and fixed position tips at the same time by
+ // moving the tooltip to the last cursor location after it is hidden
+ coords.set('top', session.currentY + options.offset);
+ coords.set('left', session.currentX + options.offset);
+ tipElement.css(coords);
+
+ // trigger powerTipClose event
+ element.trigger('powerTipClose');
+ });
+ }
+
+ /**
+ * Moves the tooltip to the users mouse cursor.
+ * @private
+ */
+ function positionTipOnCursor() {
+ var tipWidth,
+ tipHeight,
+ coords,
+ collisions,
+ collisionCount;
+
+ // to support having fixed tooltips on the same page as cursor tooltips,
+ // where both instances are referencing the same tooltip element, we
+ // need to keep track of the mouse position constantly, but we should
+ // only set the tip location if a fixed tip is not currently open, a tip
+ // open is imminent or active, and the tooltip element in question does
+ // have a mouse-follow using it.
+ if (!session.isFixedTipOpen && (session.isTipOpen || (session.tipOpenImminent && tipElement.data(DATA_HASMOUSEMOVE)))) {
+ // grab measurements
+ tipWidth = tipElement.outerWidth();
+ tipHeight = tipElement.outerHeight();
+ coords = new CSSCoordinates();
+
+ // grab collisions
+ coords.set('top', session.currentY + options.offset);
+ coords.set('left', session.currentX + options.offset);
+ collisions = getViewportCollisions(
+ coords,
+ tipWidth,
+ tipHeight
+ );
+
+ // handle tooltip view port collisions
+ if (collisions !== Collision.none) {
+ collisionCount = countFlags(collisions);
+ if (collisionCount === 1) {
+ // if there is only one collision (bottom or right) then
+ // simply constrain the tooltip to the view port
+ if (collisions === Collision.right) {
+ coords.set('left', session.scrollLeft + session.windowWidth - tipWidth);
+ } else if (collisions === Collision.bottom) {
+ coords.set('top', session.scrollTop + session.windowHeight - tipHeight);
+ }
+ } else {
+ // if the tooltip has more than one collision then it is
+ // trapped in the corner and should be flipped to get it out
+ // of the users way
+ coords.set('left', session.currentX - tipWidth - options.offset);
+ coords.set('top', session.currentY - tipHeight - options.offset);
+ }
+ }
+
+ // position the tooltip
+ tipElement.css(coords);
+ }
+ }
+
+ /**
+ * Sets the tooltip to the correct position relative to the specified target
+ * element. Based on options settings.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ */
+ function positionTipOnElement(element) {
+ var priorityList,
+ finalPlacement;
+
+ // when the followMouse option is enabled and the "force open" flag is
+ // set we revert to static positioning. since the developer may not have
+ // considered this scenario we should use smart placement
+ if (options.smartPlacement || (options.followMouse && element.data(DATA_FORCEDOPEN))) {
+ priorityList = $.fn.powerTip.smartPlacementLists[options.placement];
+
+ // iterate over the priority list and use the first placement option
+ // that does not collide with the view port. if they all collide
+ // then the last placement in the list will be used.
+ $.each(priorityList, function(idx, pos) {
+ // place tooltip and find collisions
+ var collisions = getViewportCollisions(
+ placeTooltip(element, pos),
+ tipElement.outerWidth(),
+ tipElement.outerHeight()
+ );
+
+ // update the final placement variable
+ finalPlacement = pos;
+
+ // break if there were no collisions
+ return collisions !== Collision.none;
+ });
+ } else {
+ // if we're not going to use the smart placement feature then just
+ // compute the coordinates and do it
+ placeTooltip(element, options.placement);
+ finalPlacement = options.placement;
+ }
+
+ // add placement as class for CSS arrows
+ tipElement.removeClass('w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt');
+ tipElement.addClass(finalPlacement);
+ }
+
+ /**
+ * Sets the tooltip position to the appropriate values to show the tip at
+ * the specified placement. This function will iterate and test the tooltip
+ * to support elastic tooltips.
+ * @private
+ * @param {jQuery} element The element that the tooltip should target.
+ * @param {string} placement The placement for the tooltip.
+ * @return {CSSCoordinates} A CSSCoordinates object with the top, left, and
+ * right position values.
+ */
+ function placeTooltip(element, placement) {
+ var iterationCount = 0,
+ tipWidth,
+ tipHeight,
+ coords = new CSSCoordinates();
+
+ // set the tip to 0,0 to get the full expanded width
+ coords.set('top', 0);
+ coords.set('left', 0);
+ tipElement.css(coords);
+
+ // to support elastic tooltips we need to check for a change in the
+ // rendered dimensions after the tooltip has been positioned
+ do {
+ // grab the current tip dimensions
+ tipWidth = tipElement.outerWidth();
+ tipHeight = tipElement.outerHeight();
+
+ // get placement coordinates
+ coords = placementCalculator.compute(
+ element,
+ placement,
+ tipWidth,
+ tipHeight,
+ options.offset
+ );
+
+ // place the tooltip
+ tipElement.css(coords);
+ } while (
+ // sanity check: limit to 5 iterations, and...
+ ++iterationCount <= 5 &&
+ // try again if the dimensions changed after placement
+ (tipWidth !== tipElement.outerWidth() || tipHeight !== tipElement.outerHeight())
+ );
+
+ return coords;
+ }
+
+ /**
+ * Checks for a tooltip desync and closes the tooltip if one occurs.
+ * @private
+ */
+ function closeDesyncedTip() {
+ var isDesynced = false,
+ hasDesyncableCloseEvent = $.grep(
+ [ 'mouseleave', 'mouseout', 'blur', 'focusout' ],
+ function(eventType) {
+ return $.inArray(eventType, options.closeEvents) !== -1;
+ }
+ ).length > 0;
+
+ // It is possible for the mouse cursor to leave an element without
+ // firing the mouseleave or blur event. This most commonly happens when
+ // the element is disabled under mouse cursor. If this happens it will
+ // result in a desynced tooltip because the tooltip was never asked to
+ // close. So we should periodically check for a desync situation and
+ // close the tip if such a situation arises.
+ if (session.isTipOpen && !session.isClosing && !session.delayInProgress && hasDesyncableCloseEvent) {
+ if (session.activeHover.data(DATA_HASACTIVEHOVER) === false || session.activeHover.is(':disabled')) {
+ // user moused onto another tip or active hover is disabled
+ isDesynced = true;
+ } else if (!isMouseOver(session.activeHover) && !session.activeHover.is(':focus') && !session.activeHover.data(DATA_FORCEDOPEN)) {
+ // hanging tip - have to test if mouse position is not over the
+ // active hover and not over a tooltip set to let the user
+ // interact with it.
+ // for keyboard navigation: this only counts if the element does
+ // not have focus.
+ // for tooltips opened via the api: we need to check if it has
+ // the forcedOpen flag.
+ if (tipElement.data(DATA_MOUSEONTOTIP)) {
+ if (!isMouseOver(tipElement)) {
+ isDesynced = true;
+ }
+ } else {
+ isDesynced = true;
+ }
+ }
+
+ if (isDesynced) {
+ // close the desynced tip
+ hideTip(session.activeHover);
+ }
+ }
+ }
+
+ // expose methods
+ this.showTip = beginShowTip;
+ this.hideTip = hideTip;
+ this.resetPosition = positionTipOnElement;
+ }
+
+ /**
+ * Determine whether a jQuery object is an SVG element
+ * @private
+ * @param {jQuery} element The element to check
+ * @return {boolean} Whether this is an SVG element
+ */
+ function isSvgElement(element) {
+ return Boolean(window.SVGElement && element[0] instanceof SVGElement);
+ }
+
+ /**
+ * Determines if the specified jQuery.Event object has mouse data.
+ * @private
+ * @param {jQuery.Event=} event The jQuery.Event object to test.
+ * @return {boolean} True if there is mouse data, otherwise false.
+ */
+ function isMouseEvent(event) {
+ return Boolean(event && $.inArray(event.type, MOUSE_EVENTS) > -1 &&
+ typeof event.pageX === 'number');
+ }
+
+ /**
+ * Initializes the viewport dimension cache and hooks up the mouse position
+ * tracking and viewport dimension tracking events.
+ * Prevents attaching the events more than once.
+ * @private
+ */
+ function initTracking() {
+ if (!session.mouseTrackingActive) {
+ session.mouseTrackingActive = true;
+
+ // grab the current viewport dimensions on load
+ getViewportDimensions();
+ $(getViewportDimensions);
+
+ // hook mouse move tracking
+ $document.on('mousemove' + EVENT_NAMESPACE, trackMouse);
+
+ // hook viewport dimensions tracking
+ $window.on('resize' + EVENT_NAMESPACE, trackResize);
+ $window.on('scroll' + EVENT_NAMESPACE, trackScroll);
+ }
+ }
+
+ /**
+ * Updates the viewport dimensions cache.
+ * @private
+ */
+ function getViewportDimensions() {
+ session.scrollLeft = $window.scrollLeft();
+ session.scrollTop = $window.scrollTop();
+ session.windowWidth = $window.width();
+ session.windowHeight = $window.height();
+ }
+
+ /**
+ * Updates the window size info in the viewport dimensions cache.
+ * @private
+ */
+ function trackResize() {
+ session.windowWidth = $window.width();
+ session.windowHeight = $window.height();
+ }
+
+ /**
+ * Updates the scroll offset info in the viewport dimensions cache.
+ * @private
+ */
+ function trackScroll() {
+ var x = $window.scrollLeft(),
+ y = $window.scrollTop();
+ if (x !== session.scrollLeft) {
+ session.currentX += x - session.scrollLeft;
+ session.scrollLeft = x;
+ }
+ if (y !== session.scrollTop) {
+ session.currentY += y - session.scrollTop;
+ session.scrollTop = y;
+ }
+ }
+
+ /**
+ * Saves the current mouse coordinates to the session object.
+ * @private
+ * @param {jQuery.Event} event The mousemove event for the document.
+ */
+ function trackMouse(event) {
+ session.currentX = event.pageX;
+ session.currentY = event.pageY;
+ }
+
+ /**
+ * Tests if the mouse is currently over the specified element.
+ * @private
+ * @param {jQuery} element The element to check for hover.
+ * @return {boolean} True if the mouse is over the element, otherwise false.
+ */
+ function isMouseOver(element) {
+ // use getBoundingClientRect() because jQuery's width() and height()
+ // methods do not work with SVG elements
+ // compute width/height because those properties do not exist on the object
+ // returned by getBoundingClientRect() in older versions of IE
+ var elementPosition = element.offset(),
+ elementBox = element[0].getBoundingClientRect(),
+ elementWidth = elementBox.right - elementBox.left,
+ elementHeight = elementBox.bottom - elementBox.top;
+
+ return session.currentX >= elementPosition.left &&
+ session.currentX <= elementPosition.left + elementWidth &&
+ session.currentY >= elementPosition.top &&
+ session.currentY <= elementPosition.top + elementHeight;
+ }
+
+ /**
+ * Fetches the tooltip content from the specified element's data attributes.
+ * @private
+ * @param {jQuery} element The element to get the tooltip content for.
+ * @return {(string|jQuery|undefined)} The text/HTML string, jQuery object, or
+ * undefined if there was no tooltip content for the element.
+ */
+ function getTooltipContent(element) {
+ var tipText = element.data(DATA_POWERTIP),
+ tipObject = element.data(DATA_POWERTIPJQ),
+ tipTarget = element.data(DATA_POWERTIPTARGET),
+ targetElement,
+ content;
+
+ if (tipText) {
+ if ($.isFunction(tipText)) {
+ tipText = tipText.call(element[0]);
+ }
+ content = tipText;
+ } else if (tipObject) {
+ if ($.isFunction(tipObject)) {
+ tipObject = tipObject.call(element[0]);
+ }
+ if (tipObject.length > 0) {
+ content = tipObject.clone(true, true);
+ }
+ } else if (tipTarget) {
+ targetElement = $('#' + tipTarget);
+ if (targetElement.length > 0) {
+ content = targetElement.html();
+ }
+ }
+
+ return content;
+ }
+
+ /**
+ * Finds any viewport collisions that an element (the tooltip) would have if it
+ * were absolutely positioned at the specified coordinates.
+ * @private
+ * @param {CSSCoordinates} coords Coordinates for the element.
+ * @param {number} elementWidth Width of the element in pixels.
+ * @param {number} elementHeight Height of the element in pixels.
+ * @return {number} Value with the collision flags.
+ */
+ function getViewportCollisions(coords, elementWidth, elementHeight) {
+ var viewportTop = session.scrollTop,
+ viewportLeft = session.scrollLeft,
+ viewportBottom = viewportTop + session.windowHeight,
+ viewportRight = viewportLeft + session.windowWidth,
+ collisions = Collision.none;
+
+ if (coords.top < viewportTop || Math.abs(coords.bottom - session.windowHeight) - elementHeight < viewportTop) {
+ collisions |= Collision.top;
+ }
+ if (coords.top + elementHeight > viewportBottom || Math.abs(coords.bottom - session.windowHeight) > viewportBottom) {
+ collisions |= Collision.bottom;
+ }
+ if (coords.left < viewportLeft || coords.right + elementWidth > viewportRight) {
+ collisions |= Collision.left;
+ }
+ if (coords.left + elementWidth > viewportRight || coords.right < viewportLeft) {
+ collisions |= Collision.right;
+ }
+
+ return collisions;
+ }
+
+ /**
+ * Counts the number of bits set on a flags value.
+ * @param {number} value The flags value.
+ * @return {number} The number of bits that have been set.
+ */
+ function countFlags(value) {
+ var count = 0;
+ while (value) {
+ value &= value - 1;
+ count++;
+ }
+ return count;
+ }
+
+ // return api for commonjs and amd environments
+ return $.powerTip;
+}));
diff --git a/jquery/jquery.powertip-1.3.1.mod.min.js b/jquery/jquery.powertip-1.3.1.mod.min.js
new file mode 100644
index 0000000..173b645
--- /dev/null
+++ b/jquery/jquery.powertip-1.3.1.mod.min.js
@@ -0,0 +1,8 @@
+/*!
+ PowerTip v1.3.1 (2018-04-15)
+ https://stevenbenner.github.io/jquery-powertip/
+ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory(require("jquery"))}else{factory(root.jQuery)}})(this,function($){var $document=$(document),$window=$(window),$body=$("body");var DATA_DISPLAYCONTROLLER="displayController",DATA_HASACTIVEHOVER="hasActiveHover",DATA_FORCEDOPEN="forcedOpen",DATA_HASMOUSEMOVE="hasMouseMove",DATA_MOUSEONTOTIP="mouseOnToPopup",DATA_ORIGINALTITLE="originalTitle",DATA_POWERTIP="powertip",DATA_POWERTIPJQ="powertipjq",DATA_POWERTIPTARGET="powertiptarget",EVENT_NAMESPACE=".powertip",RAD2DEG=180/Math.PI,MOUSE_EVENTS=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"];var session={tooltips:null,isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var Collision={none:0,top:1,bottom:2,left:4,right:8};$.fn.powerTip=function(opts,arg){var targetElements=this,options,tipController;if(!targetElements.length){return targetElements}if($.type(opts)==="string"&&$.powerTip[opts]){return $.powerTip[opts].call(targetElements,targetElements,arg)}options=$.extend({},$.fn.powerTip.defaults,opts);tipController=new TooltipController(options);initTracking();targetElements.each(function elementSetup(){var $this=$(this),dataPowertip=$this.data(DATA_POWERTIP),dataElem=$this.data(DATA_POWERTIPJQ),dataTarget=$this.data(DATA_POWERTIPTARGET),title=$this.attr("title");if(!dataPowertip&&!dataTarget&&!dataElem&&title){$this.data(DATA_POWERTIP,title);$this.data(DATA_ORIGINALTITLE,title);$this.removeAttr("title")}$this.data(DATA_DISPLAYCONTROLLER,new DisplayController($this,options,tipController))});if(!options.manual){$.each(options.openEvents,function(idx,evt){if($.inArray(evt,options.closeEvents)>-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference<options.intentSensitivity){cancelClose();closeAnyDelayed();tipController.showTip(element)}else{session.previousX=session.currentX;session.previousY=session.currentY;openTooltip()}}function cancelTimer(stopClose){hoverTimer=clearTimeout(hoverTimer);if(session.closeDelayTimeout&&myCloseDelay===session.closeDelayTimeout||stopClose){cancelClose()}}function cancelClose(){session.closeDelayTimeout=clearTimeout(session.closeDelayTimeout);session.delayInProgress=false}function closeAnyDelayed(){if(session.delayInProgress&&session.activeHover&&!session.activeHover.is(element)){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true)}}function repositionTooltip(){tipController.resetPosition(element)}this.show=openTooltip;this.hide=closeTooltip;this.cancel=cancelTimer;this.resetPosition=repositionTooltip}function PlacementCalculator(){function computePlacementCoords(element,placement,tipWidth,tipHeight,offset){var placementBase=placement.split("-")[0],coords=new CSSCoordinates,position;if(isSvgElement(element)){position=getSvgPlacement(element,placementBase)}else{position=getHtmlPlacement(element,placementBase)}switch(placement){case"n":coords.set("left",position.left-tipWidth/2);coords.set("bottom",session.windowHeight-position.top+offset);break;case"e":coords.set("left",position.left+offset);coords.set("top",position.top-tipHeight/2);break;case"s":coords.set("left",position.left-tipWidth/2);coords.set("top",position.top+offset);break;case"w":coords.set("top",position.top-tipHeight/2);coords.set("right",session.windowWidth-position.left+offset);break;case"nw":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"nw-alt":coords.set("left",position.left);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne":coords.set("left",position.left-20);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne-alt":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left);break;case"sw":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"sw-alt":coords.set("left",position.left);coords.set("top",position.top+offset);break;case"se":coords.set("left",position.left-20);coords.set("top",position.top+offset);break;case"se-alt":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left);break}return coords}function getHtmlPlacement(element,placement){var objectOffset=element.offset(),objectWidth=element.outerWidth(),objectHeight=element.outerHeight(),left,top;switch(placement){case"n":left=objectOffset.left+objectWidth/2;top=objectOffset.top;break;case"e":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight/2;break;case"s":left=objectOffset.left+objectWidth/2;top=objectOffset.top+objectHeight;break;case"w":left=objectOffset.left;top=objectOffset.top+objectHeight/2;break;case"nw":left=objectOffset.left;top=objectOffset.top;break;case"ne":left=objectOffset.left+objectWidth;top=objectOffset.top;break;case"sw":left=objectOffset.left;top=objectOffset.top+objectHeight;break;case"se":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight;break}return{top:top,left:left}}function getSvgPlacement(element,placement){var svgElement=element.closest("svg")[0],domElement=element[0],point=svgElement.createSVGPoint(),boundingBox=domElement.getBBox(),matrix=domElement.getScreenCTM(),halfWidth=boundingBox.width/2,halfHeight=boundingBox.height/2,placements=[],placementKeys=["nw","n","ne","e","se","s","sw","w"],coords,rotation,steps,x;function pushPlacement(){placements.push(point.matrixTransform(matrix))}point.x=boundingBox.x;point.y=boundingBox.y;pushPlacement();point.x+=halfWidth;pushPlacement();point.x+=halfWidth;pushPlacement();point.y+=halfHeight;pushPlacement();point.y+=halfHeight;pushPlacement();point.x-=halfWidth;pushPlacement();point.x-=halfWidth;pushPlacement();point.y-=halfHeight;pushPlacement();if(placements[0].y!==placements[1].y||placements[0].x!==placements[7].x){rotation=Math.atan2(matrix.b,matrix.a)*RAD2DEG;steps=Math.ceil((rotation%360-22.5)/45);if(steps<1){steps+=8}while(steps--){placementKeys.push(placementKeys.shift())}}for(x=0;x<placements.length;x++){if(placementKeys[x]===placement){coords=placements[x];break}}return{top:coords.y+session.scrollTop,left:coords.x+session.scrollLeft}}this.compute=computePlacementCoords}function TooltipController(options){var placementCalculator=new PlacementCalculator,tipElement=$("#"+options.popupId);if(tipElement.length===0){tipElement=$("<div/>",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.top<viewportTop||Math.abs(coords.bottom-session.windowHeight)-elementHeight<viewportTop){collisions|=Collision.top}if(coords.top+elementHeight>viewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.left<viewportLeft||coords.right+elementWidth>viewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right<viewportLeft){collisions|=Collision.right}return collisions}function countFlags(value){var count=0;while(value){value&=value-1;count++}return count}return $.powerTip}); \ No newline at end of file
diff --git a/liblodepng/CMakeLists.txt b/liblodepng/CMakeLists.txt
new file mode 100644
index 0000000..e62835f
--- /dev/null
+++ b/liblodepng/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(lodepng STATIC
+lodepng.cpp
+)
diff --git a/src/lodepng.cpp b/liblodepng/lodepng.cpp
index 1906f09..6e28587 100644
--- a/src/lodepng.cpp
+++ b/liblodepng/lodepng.cpp
@@ -29,7 +29,6 @@ You are free to name this file lodepng.cpp or lodepng.c depending on your usage.
*/
#include "lodepng.h"
-#include "portable.h"
#define USE_BRUTE_FORCE_ENCODING 1
@@ -2435,8 +2434,7 @@ void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source)
/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename)
{
- FILE* file;
- file = portable_fopen(filename, "wb" );
+ FILE* file = fopen(filename,"wb");
if(!file) return 79;
fwrite((char*)buffer , 1 , buffersize, file);
fclose(file);
diff --git a/src/lodepng.h b/liblodepng/lodepng.h
index fb079cc..36d0e68 100644
--- a/src/lodepng.h
+++ b/liblodepng/lodepng.h
@@ -32,6 +32,10 @@ freely, subject to the following restrictions:
#include <stdlib.h>
#include <string.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* ////////////////////////////////////////////////////////////////////////// */
/* LodeFlate & LodeZlib Setting structs */
/* ////////////////////////////////////////////////////////////////////////// */
@@ -115,5 +119,9 @@ void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsi
//unsigned LodePNG_loadFile(unsigned char** out, size_t* outsize, const char* filename);
unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/libmd5/Makefile.in b/libmd5/Makefile.in
deleted file mode 100644
index 08c03b8..0000000
--- a/libmd5/Makefile.in
+++ /dev/null
@@ -1,18 +0,0 @@
-all: Makefile.libmd5
- $(MAKE) -f Makefile.libmd5
-
-clean: Makefile.libmd5
- $(MAKE) -f Makefile.libmd5 clean
-
-distclean: clean
- $(RM) -f Makefile.libmd5 libmd5.pro Makefile
-
-realclean: distclean
-
-tmake:
- $(ENV) $(PERL) "$(TMAKE)" libmd5.pro >Makefile.libmd5
-
-Makefile.libmd5: libmd5.pro
- $(ENV) $(PERL) "$(TMAKE)" libmd5.pro >Makefile.libmd5
-
-install:
diff --git a/libmd5/libmd5.pro.in b/libmd5/libmd5.pro.in
deleted file mode 100644
index 5516174..0000000
--- a/libmd5/libmd5.pro.in
+++ /dev/null
@@ -1,10 +0,0 @@
-TEMPLATE = lib
-CONFIG = warn_on staticlib $extraopts
-HEADERS = md5.h md5_loc.h
-SOURCES = md5.c
-win32:INCLUDEPATH += .
-win32-g++:TMAKE_CFLAGS += -D__CYGWIN__ -DALL_STATIC
-DESTDIR = ../lib
-TARGET = md5
-OBJECTS_DIR = ../objects/md5
-
diff --git a/libmscgen/CMakeLists.txt b/libmscgen/CMakeLists.txt
new file mode 100644
index 0000000..3d67ed3
--- /dev/null
+++ b/libmscgen/CMakeLists.txt
@@ -0,0 +1,38 @@
+include_directories(
+ ${CMAKE_SOURCE_DIR}/liblodepng
+ ${CMAKE_SOURCE_DIR}/libmscgen
+ ${GENERATED_SRC}
+)
+
+add_library(mscgen
+gd.c
+gd_security.c
+gdfontt.c
+gdtables.c
+gd_color.c
+gdfonts.c
+gdhelpers.c
+gd_lodepng.c
+mscgen_adraw.c
+mscgen_gd_out.c
+mscgen_ps_out.c
+mscgen_null_out.c
+${GENERATED_SRC}/mscgen_language.cpp
+${GENERATED_SRC}/mscgen_lexer.cpp
+mscgen_api.c
+mscgen_msc.c
+mscgen_safe.c
+mscgen_svg_out.c
+mscgen_usage.c
+mscgen_utf8.c
+)
+
+
+FLEX_TARGET(mscgen_lexer
+ mscgen_lexer.l
+ ${GENERATED_SRC}/mscgen_lexer.cpp
+ COMPILE_FLAGS "${LEX_FLAGS}")
+BISON_TARGET(mscgen_language
+ mscgen_language.y
+ ${GENERATED_SRC}/mscgen_language.cpp
+ COMPILE_FLAGS "${YACC_FLAGS}")
diff --git a/libmscgen/COPYING b/libmscgen/COPYING
new file mode 100644
index 0000000..7d122e1
--- /dev/null
+++ b/libmscgen/COPYING
@@ -0,0 +1,287 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+TTPCom Ltd., hereby disclaims all copyright interest in the program `mscgen'
+(which renders message sequence charts) written by Michael McTernan.
+
+Rob Meades of TTPCom Ltd, 1 August 2005
+Rob Meades, director of Software
diff --git a/libmscgen/README.txt b/libmscgen/README.txt
new file mode 100644
index 0000000..06b3902
--- /dev/null
+++ b/libmscgen/README.txt
@@ -0,0 +1,20 @@
+Issue 6880 (https://github.com/doxygen/doxygen/issues/6880) required fixes to the mscgen tool.
+Since this tool is no longer maintained, it was decided to build mscgen as part of doxygen.
+This directory contains the mscgen code.
+
+Since mscgen depends on libgd for PNG output, a part of the gd library is included as well.
+Instead of using libpng as PNG generator, the lodepng library is used. This PNG library was
+already part of doxygen. Module gd_lodepng.c was added to make libgd use lodepng.
+
+Original copyright statement follows:
+
+LICENCE
+=======
+
+Mscgen, Copyright (C) 2010 Michael C McTernan,
+ Michael.McTernan.2001@cs.bris.ac.uk
+Mscgen comes with ABSOLUTELY NO WARRANTY. Mscgen is free software, and you
+are welcome to redistribute it under certain conditions; see the COPYING
+file for details.
+
+
diff --git a/libmscgen/gd.c b/libmscgen/gd.c
new file mode 100644
index 0000000..7f0a258
--- /dev/null
+++ b/libmscgen/gd.c
@@ -0,0 +1,4539 @@
+/* $Id$ */
+
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gd_intern.h"
+
+/* 2.03: don't include zlib here or we can't build without PNG */
+#include "gd.h"
+#include "gdhelpers.h"
+#include "gd_color.h"
+#include "gd_errors.h"
+
+/* 2.0.12: this now checks the clipping rectangle */
+#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < (im)->cy1) || ((y) > (im)->cy2)) || (((x) < (im)->cx1) || ((x) > (im)->cx2))))
+
+#ifdef _OSD_POSIX /* BS2000 uses the EBCDIC char set instead of ASCII */
+#define CHARSET_EBCDIC
+#define __attribute__(any) /*nothing */
+#endif
+/*_OSD_POSIX*/
+
+#ifndef CHARSET_EBCDIC
+#define ASC(ch) ch
+#else /*CHARSET_EBCDIC */
+#define ASC(ch) gd_toascii[(unsigned char)ch]
+static const unsigned char gd_toascii[256] = {
+ /*00 */ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
+ 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................ */
+ /*10 */ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
+ 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................ */
+ /*20 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................ */
+ /*30 */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................ */
+ /*40 */ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+| */
+ /*50 */ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);. */
+ /*60 */ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ /*-/........^,%_>?*/
+ /*70 */ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'=" */
+ /*80 */ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi...... */
+ /*90 */ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr...... */
+ /*a0 */ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz...... */
+ /*b0 */ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\].. */
+ /*c0 */ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI...... */
+ /*d0 */ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR...... */
+ /*e0 */ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ...... */
+ /*f0 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~ */
+};
+#endif /*CHARSET_EBCDIC */
+
+extern const int gdCosT[];
+extern const int gdSinT[];
+
+/**
+ * Group: Error Handling
+ */
+
+void gd_stderr_error(int priority, const char *format, va_list args)
+{
+ switch (priority) {
+ case GD_ERROR:
+ fputs("GD Error: ", stderr);
+ break;
+ case GD_WARNING:
+ fputs("GD Warning: ", stderr);
+ break;
+ case GD_NOTICE:
+ fputs("GD Notice: ", stderr);
+ break;
+ case GD_INFO:
+ fputs("GD Info: ", stderr);
+ break;
+ case GD_DEBUG:
+ fputs("GD Debug: ", stderr);
+ break;
+ }
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+}
+
+static gdErrorMethod gd_error_method = gd_stderr_error;
+
+static void _gd_error_ex(int priority, const char *format, va_list args)
+{
+ if (gd_error_method) {
+ gd_error_method(priority, format, args);
+ }
+}
+
+void gd_error(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ _gd_error_ex(GD_WARNING, format, args);
+ va_end(args);
+}
+void gd_error_ex(int priority, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ _gd_error_ex(priority, format, args);
+ va_end(args);
+}
+
+/*
+ Function: gdSetErrorMethod
+*/
+BGD_DECLARE(void) gdSetErrorMethod(gdErrorMethod error_method)
+{
+ gd_error_method = error_method;
+}
+
+/*
+ Function: gdClearErrorMethod
+*/
+BGD_DECLARE(void) gdClearErrorMethod(void)
+{
+ gd_error_method = gd_stderr_error;
+}
+
+static void gdImageBrushApply (gdImagePtr im, int x, int y);
+static void gdImageTileApply (gdImagePtr im, int x, int y);
+
+BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
+
+/**
+ * Group: Creation and Destruction
+ */
+
+/*
+ Function: gdImageCreate
+
+ gdImageCreate is called to create palette-based images, with no
+ more than 256 colors. The image must eventually be destroyed using
+ gdImageDestroy().
+
+ Parameters:
+
+ sx - The image width.
+ sy - The image height.
+
+ Returns:
+
+ A pointer to the new image or NULL if an error occurred.
+
+ Example:
+ (start code)
+
+ gdImagePtr im;
+ im = gdImageCreate(64, 64);
+ // ... Use the image ...
+ gdImageDestroy(im);
+
+ (end code)
+
+ See Also:
+
+ <gdImageCreateTrueColor>
+
+ */
+BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
+{
+ int i;
+ gdImagePtr im;
+
+ if (overflow2(sx, sy)) {
+ return NULL;
+ }
+
+ if (overflow2(sizeof (unsigned char *), sy)) {
+ return NULL;
+ }
+ if (overflow2(sizeof (unsigned char *), sx)) {
+ return NULL;
+ }
+
+ im = (gdImage *) gdCalloc(1, sizeof(gdImage));
+ if (!im) {
+ return NULL;
+ }
+
+ /* Row-major ever since gd 1.3 */
+ im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
+ if (!im->pixels) {
+ gdFree(im);
+ return NULL;
+ }
+
+ im->polyInts = 0;
+ im->polyAllocated = 0;
+ im->brush = 0;
+ im->tile = 0;
+ im->style = 0;
+ for (i = 0; (i < sy); i++) {
+ /* Row-major ever since gd 1.3 */
+ im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char));
+ if (!im->pixels[i]) {
+ for (--i ; i >= 0; i--) {
+ gdFree(im->pixels[i]);
+ }
+ gdFree(im->pixels);
+ gdFree(im);
+ return NULL;
+ }
+
+ }
+ im->sx = sx;
+ im->sy = sy;
+ im->colorsTotal = 0;
+ im->transparent = (-1);
+ im->interlace = 0;
+ im->thick = 1;
+ im->AA = 0;
+ for (i = 0; (i < gdMaxColors); i++) {
+ im->open[i] = 1;
+ };
+ im->trueColor = 0;
+ im->tpixels = 0;
+ im->cx1 = 0;
+ im->cy1 = 0;
+ im->cx2 = im->sx - 1;
+ im->cy2 = im->sy - 1;
+ im->res_x = GD_RESOLUTION;
+ im->res_y = GD_RESOLUTION;
+ im->interpolation = NULL;
+ im->interpolation_id = GD_BILINEAR_FIXED;
+ return im;
+}
+
+
+
+/*
+ Function: gdImageCreateTrueColor
+
+ <gdImageCreateTrueColor> is called to create truecolor images,
+ with an essentially unlimited number of colors. Invoke
+ <gdImageCreateTrueColor> with the x and y dimensions of the
+ desired image. <gdImageCreateTrueColor> returns a <gdImagePtr>
+ to the new image, or NULL if unable to allocate the image. The
+ image must eventually be destroyed using <gdImageDestroy>().
+
+ Truecolor images are always filled with black at creation
+ time. There is no concept of a "background" color index.
+
+ Parameters:
+
+ sx - The image width.
+ sy - The image height.
+
+ Returns:
+
+ A pointer to the new image or NULL if an error occurred.
+
+ Example:
+ (start code)
+
+ gdImagePtr im;
+ im = gdImageCreateTrueColor(64, 64);
+ // ... Use the image ...
+ gdImageDestroy(im);
+
+ (end code)
+
+ See Also:
+
+ <gdImageCreateTrueColor>
+
+*/
+BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy)
+{
+ int i;
+ gdImagePtr im;
+
+ if (overflow2(sx, sy)) {
+ return NULL;
+ }
+
+ if (overflow2(sizeof (int *), sy)) {
+ return 0;
+ }
+
+ if (overflow2(sizeof(int *), sx)) {
+ return NULL;
+ }
+
+ im = (gdImage *) gdMalloc (sizeof (gdImage));
+ if (!im) {
+ return 0;
+ }
+ memset (im, 0, sizeof (gdImage));
+
+ im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
+ if (!im->tpixels) {
+ gdFree(im);
+ return 0;
+ }
+ im->polyInts = 0;
+ im->polyAllocated = 0;
+ im->brush = 0;
+ im->tile = 0;
+ im->style = 0;
+ for (i = 0; (i < sy); i++) {
+ im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int));
+ if (!im->tpixels[i]) {
+ /* 2.0.34 */
+ i--;
+ while (i >= 0) {
+ gdFree(im->tpixels[i]);
+ i--;
+ }
+ gdFree(im->tpixels);
+ gdFree(im);
+ return 0;
+ }
+ }
+ im->sx = sx;
+ im->sy = sy;
+ im->transparent = (-1);
+ im->interlace = 0;
+ im->trueColor = 1;
+ /* 2.0.2: alpha blending is now on by default, and saving of alpha is
+ off by default. This allows font antialiasing to work as expected
+ on the first try in JPEGs -- quite important -- and also allows
+ for smaller PNGs when saving of alpha channel is not really
+ desired, which it usually isn't! */
+ im->saveAlphaFlag = 0;
+ im->alphaBlendingFlag = 1;
+ im->thick = 1;
+ im->AA = 0;
+ im->cx1 = 0;
+ im->cy1 = 0;
+ im->cx2 = im->sx - 1;
+ im->cy2 = im->sy - 1;
+ im->res_x = GD_RESOLUTION;
+ im->res_y = GD_RESOLUTION;
+ im->interpolation = NULL;
+ im->interpolation_id = GD_BILINEAR_FIXED;
+ return im;
+}
+
+/*
+ Function: gdImageDestroy
+
+ <gdImageDestroy> is used to free the memory associated with an
+ image. It is important to invoke <gdImageDestroy> before exiting
+ your program or assigning a new image to a <gdImagePtr> variable.
+
+ Parameters:
+
+ im - Pointer to the gdImage to delete.
+
+ Returns:
+
+ Nothing.
+
+ Example:
+ (start code)
+
+ gdImagePtr im;
+ im = gdImageCreate(10, 10);
+ // ... Use the image ...
+ // Now destroy it
+ gdImageDestroy(im);
+
+ (end code)
+
+*/
+
+BGD_DECLARE(void) gdImageDestroy (gdImagePtr im)
+{
+ int i;
+ if (im->pixels) {
+ for (i = 0; (i < im->sy); i++) {
+ gdFree (im->pixels[i]);
+ }
+ gdFree (im->pixels);
+ }
+ if (im->tpixels) {
+ for (i = 0; (i < im->sy); i++) {
+ gdFree (im->tpixels[i]);
+ }
+ gdFree (im->tpixels);
+ }
+ if (im->polyInts) {
+ gdFree (im->polyInts);
+ }
+ if (im->style) {
+ gdFree (im->style);
+ }
+ gdFree (im);
+}
+
+/**
+ * Group: Color
+ */
+
+/**
+ * Function: gdImageColorClosest
+ *
+ * Gets the closest color of the image
+ *
+ * This is a simplified variant of <gdImageColorClosestAlpha> where the alpha
+ * channel is always opaque.
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ *
+ * Returns:
+ * The closest color already available in the palette for palette images;
+ * the color value of the given components for truecolor images.
+ *
+ * See also:
+ * - <gdImageColorExact>
+ */
+BGD_DECLARE(int) gdImageColorClosest (gdImagePtr im, int r, int g, int b)
+{
+ return gdImageColorClosestAlpha (im, r, g, b, gdAlphaOpaque);
+}
+
+/**
+ * Function: gdImageColorClosestAlpha
+ *
+ * Gets the closest color of the image
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ * a - The value of the alpha component.
+ *
+ * Returns:
+ * The closest color already available in the palette for palette images;
+ * the color value of the given components for truecolor images.
+ *
+ * See also:
+ * - <gdImageColorExactAlpha>
+ */
+BGD_DECLARE(int) gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a)
+{
+ int i;
+ long rd, gd, bd, ad;
+ int ct = (-1);
+ int first = 1;
+ long mindist = 0;
+ if (im->trueColor) {
+ return gdTrueColorAlpha (r, g, b, a);
+ }
+ for (i = 0; (i < (im->colorsTotal)); i++) {
+ long dist;
+ if (im->open[i]) {
+ continue;
+ }
+ rd = (im->red[i] - r);
+ gd = (im->green[i] - g);
+ bd = (im->blue[i] - b);
+ /* gd 2.02: whoops, was - b (thanks to David Marwood) */
+ /* gd 2.16: was blue rather than alpha! Geez! Thanks to
+ Artur Jakub Jerzak */
+ ad = (im->alpha[i] - a);
+ dist = rd * rd + gd * gd + bd * bd + ad * ad;
+ if (first || (dist < mindist)) {
+ mindist = dist;
+ ct = i;
+ first = 0;
+ }
+ }
+ return ct;
+}
+
+/* This code is taken from http://www.acm.org/jgt/papers/SmithLyons96/hwb_rgb.html, an article
+ * on colour conversion to/from RBG and HWB colour systems.
+ * It has been modified to return the converted value as a * parameter.
+ */
+
+#define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;}
+#define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;}
+#define HWB_UNDEFINED -1
+#define SETUP_RGB(s, r, g, b) {s.R = r/255.0; s.G = g/255.0; s.B = b/255.0;}
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
+#define MAX(a,b) ((a)<(b)?(b):(a))
+#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
+
+
+/*
+ * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms. Pure
+ * red always maps to 6 in this implementation. Therefore UNDEFINED can be
+ * defined as 0 in situations where only unsigned numbers are desired.
+ */
+typedef struct {
+ float R, G, B;
+}
+RGBType;
+typedef struct {
+ float H, W, B;
+}
+HWBType;
+
+static HWBType *
+RGB_to_HWB (RGBType RGB, HWBType * HWB)
+{
+
+ /*
+ * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is
+ * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.
+ */
+
+ float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
+ int i;
+
+ w = MIN3 (R, G, B);
+ v = MAX3 (R, G, B);
+ b = 1 - v;
+ if (v == w)
+ RETURN_HWB (HWB_UNDEFINED, w, b);
+ f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
+ i = (R == w) ? 3 : ((G == w) ? 5 : 1);
+ RETURN_HWB (i - f / (v - w), w, b);
+
+}
+
+static float
+HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2)
+{
+ RGBType RGB1, RGB2;
+ HWBType HWB1, HWB2;
+ float diff;
+
+ SETUP_RGB (RGB1, r1, g1, b1);
+ SETUP_RGB (RGB2, r2, g2, b2);
+
+ RGB_to_HWB (RGB1, &HWB1);
+ RGB_to_HWB (RGB2, &HWB2);
+
+ /*
+ * I made this bit up; it seems to produce OK results, and it is certainly
+ * more visually correct than the current RGB metric. (PJW)
+ */
+
+ if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED)) {
+ diff = 0; /* Undefined hues always match... */
+ } else {
+ diff = fabs (HWB1.H - HWB2.H);
+ if (diff > 3) {
+ diff = 6 - diff; /* Remember, it's a colour circle */
+ }
+ }
+
+ diff =
+ diff * diff + (HWB1.W - HWB2.W) * (HWB1.W - HWB2.W) + (HWB1.B -
+ HWB2.B) * (HWB1.B -
+ HWB2.B);
+
+ return diff;
+}
+
+
+#if 0
+/*
+ * This is not actually used, but is here for completeness, in case someone wants to
+ * use the HWB stuff for anything else...
+ */
+static RGBType *
+HWB_to_RGB (HWBType HWB, RGBType * RGB)
+{
+
+ /*
+ * H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1].
+ * RGB are each returned on [0, 1].
+ */
+
+ float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f;
+ int i;
+
+ v = 1 - b;
+ if (h == HWB_UNDEFINED)
+ RETURN_RGB (v, v, v);
+ i = floor (h);
+ f = h - i;
+ if (i & 1)
+ f = 1 - f; /* if i is odd */
+ n = w + f * (v - w); /* linear interpolation between w and v */
+ switch (i) {
+ case 6:
+ case 0:
+ RETURN_RGB (v, n, w);
+ case 1:
+ RETURN_RGB (n, v, w);
+ case 2:
+ RETURN_RGB (w, v, n);
+ case 3:
+ RETURN_RGB (w, n, v);
+ case 4:
+ RETURN_RGB (n, w, v);
+ case 5:
+ RETURN_RGB (v, w, n);
+ }
+
+ return RGB;
+
+}
+#endif
+
+/*
+ Function: gdImageColorClosestHWB
+*/
+BGD_DECLARE(int) gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b)
+{
+ int i;
+ /* long rd, gd, bd; */
+ int ct = (-1);
+ int first = 1;
+ float mindist = 0;
+ if (im->trueColor) {
+ return gdTrueColor (r, g, b);
+ }
+ for (i = 0; (i < (im->colorsTotal)); i++) {
+ float dist;
+ if (im->open[i]) {
+ continue;
+ }
+ dist = HWB_Diff (im->red[i], im->green[i], im->blue[i], r, g, b);
+ if (first || (dist < mindist)) {
+ mindist = dist;
+ ct = i;
+ first = 0;
+ }
+ }
+ return ct;
+}
+
+/**
+ * Function: gdImageColorExact
+ *
+ * Gets the exact color of the image
+ *
+ * This is a simplified variant of <gdImageColorExactAlpha> where the alpha
+ * channel is always opaque.
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ *
+ * Returns:
+ * The exact color already available in the palette for palette images; if
+ * there is no exact color, -1 is returned.
+ * For truecolor images the color value of the given components is returned.
+ *
+ * See also:
+ * - <gdImageColorClosest>
+ */
+BGD_DECLARE(int) gdImageColorExact (gdImagePtr im, int r, int g, int b)
+{
+ return gdImageColorExactAlpha (im, r, g, b, gdAlphaOpaque);
+}
+
+/**
+ * Function: gdImageColorExactAlpha
+ *
+ * Gets the exact color of the image
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ * a - The value of the alpha component.
+ *
+ * Returns:
+ * The exact color already available in the palette for palette images; if
+ * there is no exact color, -1 is returned.
+ * For truecolor images the color value of the given components is returned.
+ *
+ * See also:
+ * - <gdImageColorClosestAlpha>
+ * - <gdTrueColorAlpha>
+ */
+BGD_DECLARE(int) gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a)
+{
+ int i;
+ if (im->trueColor) {
+ return gdTrueColorAlpha (r, g, b, a);
+ }
+ for (i = 0; (i < (im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ continue;
+ }
+ if ((im->red[i] == r) &&
+ (im->green[i] == g) && (im->blue[i] == b) && (im->alpha[i] == a)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Function: gdImageColorAllocate
+ *
+ * Allocates a color
+ *
+ * This is a simplified variant of <gdImageColorAllocateAlpha> where the alpha
+ * channel is always opaque.
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ *
+ * Returns:
+ * The color value.
+ *
+ * See also:
+ * - <gdImageColorDeallocate>
+ */
+BGD_DECLARE(int) gdImageColorAllocate (gdImagePtr im, int r, int g, int b)
+{
+ return gdImageColorAllocateAlpha (im, r, g, b, gdAlphaOpaque);
+}
+
+/**
+ * Function: gdImageColorAllocateAlpha
+ *
+ * Allocates a color
+ *
+ * This is typically used for palette images, but can be used for truecolor
+ * images as well.
+ *
+ * Parameters:
+ * im - The image.
+ * r - The value of the red component.
+ * g - The value of the green component.
+ * b - The value of the blue component.
+ *
+ * Returns:
+ * The color value.
+ *
+ * See also:
+ * - <gdImageColorDeallocate>
+ */
+BGD_DECLARE(int) gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a)
+{
+ int i;
+ int ct = (-1);
+ if (im->trueColor) {
+ return gdTrueColorAlpha (r, g, b, a);
+ }
+ for (i = 0; (i < (im->colorsTotal)); i++) {
+ if (im->open[i]) {
+ ct = i;
+ break;
+ }
+ }
+ if (ct == (-1)) {
+ ct = im->colorsTotal;
+ if (ct == gdMaxColors) {
+ return -1;
+ }
+ im->colorsTotal++;
+ }
+ im->red[ct] = r;
+ im->green[ct] = g;
+ im->blue[ct] = b;
+ im->alpha[ct] = a;
+ im->open[ct] = 0;
+ return ct;
+}
+
+/*
+ Function: gdImageColorResolve
+
+ gdImageColorResolve is an alternative for the code fragment
+ (start code)
+ if ((color=gdImageColorExact(im,R,G,B)) < 0)
+ if ((color=gdImageColorAllocate(im,R,G,B)) < 0)
+ color=gdImageColorClosest(im,R,G,B);
+ (end code)
+ in a single function. Its advantage is that it is guaranteed to
+ return a color index in one search over the color table.
+*/
+
+BGD_DECLARE(int) gdImageColorResolve (gdImagePtr im, int r, int g, int b)
+{
+ return gdImageColorResolveAlpha (im, r, g, b, gdAlphaOpaque);
+}
+
+/*
+ Function: gdImageColorResolveAlpha
+*/
+BGD_DECLARE(int) gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a)
+{
+ int c;
+ int ct = -1;
+ int op = -1;
+ long rd, gd, bd, ad, dist;
+ long mindist = 4 * 255 * 255; /* init to max poss dist */
+ if (im->trueColor) {
+ return gdTrueColorAlpha (r, g, b, a);
+ }
+
+ for (c = 0; c < im->colorsTotal; c++) {
+ if (im->open[c]) {
+ op = c; /* Save open slot */
+ continue; /* Color not in use */
+ }
+ if (c == im->transparent) {
+ /* don't ever resolve to the color that has
+ * been designated as the transparent color */
+ continue;
+ }
+ rd = (long) (im->red[c] - r);
+ gd = (long) (im->green[c] - g);
+ bd = (long) (im->blue[c] - b);
+ ad = (long) (im->alpha[c] - a);
+ dist = rd * rd + gd * gd + bd * bd + ad * ad;
+ if (dist < mindist) {
+ if (dist == 0) {
+ return c; /* Return exact match color */
+ }
+ mindist = dist;
+ ct = c;
+ }
+ }
+ /* no exact match. We now know closest, but first try to allocate exact */
+ if (op == -1) {
+ op = im->colorsTotal;
+ if (op == gdMaxColors) {
+ /* No room for more colors */
+ return ct; /* Return closest available color */
+ }
+ im->colorsTotal++;
+ }
+ im->red[op] = r;
+ im->green[op] = g;
+ im->blue[op] = b;
+ im->alpha[op] = a;
+ im->open[op] = 0;
+ return op; /* Return newly allocated color */
+}
+
+/**
+ * Function: gdImageColorDeallocate
+ *
+ * Removes a palette entry
+ *
+ * This is a no-op for truecolor images.
+ *
+ * Parameters:
+ * im - The image.
+ * color - The palette index.
+ *
+ * See also:
+ * - <gdImageColorAllocate>
+ * - <gdImageColorAllocateAlpha>
+ */
+BGD_DECLARE(void) gdImageColorDeallocate (gdImagePtr im, int color)
+{
+ if (im->trueColor || (color >= gdMaxColors) || (color < 0)) {
+ return;
+ }
+ /* Mark it open. */
+ im->open[color] = 1;
+}
+
+/**
+ * Function: gdImageColorTransparent
+ *
+ * Sets the transparent color of the image
+ *
+ * Parameter:
+ * im - The image.
+ * color - The color.
+ *
+ * See also:
+ * - <gdImageGetTransparent>
+ */
+BGD_DECLARE(void) gdImageColorTransparent (gdImagePtr im, int color)
+{
+ if (color < 0) {
+ return;
+ }
+
+ if (!im->trueColor) {
+ if((color < -1) || (color >= gdMaxColors)) {
+ return;
+ }
+ if (im->transparent != -1) {
+ im->alpha[im->transparent] = gdAlphaOpaque;
+ }
+ if (color != -1) {
+ im->alpha[color] = gdAlphaTransparent;
+ }
+ }
+ im->transparent = color;
+}
+
+/*
+ Function: gdImagePaletteCopy
+*/
+BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
+{
+ int i;
+ int x, y, p;
+ int xlate[256];
+ if (to->trueColor) {
+ return;
+ }
+ if (from->trueColor) {
+ return;
+ }
+
+ for (i = 0; i < 256; i++) {
+ xlate[i] = -1;
+ };
+
+ for (y = 0; y < (to->sy); y++) {
+ for (x = 0; x < (to->sx); x++) {
+ /* Optimization: no gdImageGetPixel */
+ p = to->pixels[y][x];
+ if (xlate[p] == -1) {
+ /* This ought to use HWB, but we don't have an alpha-aware
+ version of that yet. */
+ xlate[p] =
+ gdImageColorClosestAlpha (from, to->red[p], to->green[p],
+ to->blue[p], to->alpha[p]);
+ /*printf("Mapping %d (%d, %d, %d, %d) to %d (%d, %d, %d, %d)\n", */
+ /* p, to->red[p], to->green[p], to->blue[p], to->alpha[p], */
+ /* xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]], from->alpha[xlate[p]]); */
+ };
+ /* Optimization: no gdImageSetPixel */
+ to->pixels[y][x] = xlate[p];
+ };
+ };
+
+ for (i = 0; (i < (from->colorsTotal)); i++) {
+ /*printf("Copying color %d (%d, %d, %d, %d)\n", i, from->red[i], from->blue[i], from->green[i], from->alpha[i]); */
+ to->red[i] = from->red[i];
+ to->blue[i] = from->blue[i];
+ to->green[i] = from->green[i];
+ to->alpha[i] = from->alpha[i];
+ to->open[i] = 0;
+ };
+
+ for (i = from->colorsTotal; (i < to->colorsTotal); i++) {
+ to->open[i] = 1;
+ };
+
+ to->colorsTotal = from->colorsTotal;
+
+}
+
+/*
+ Function: gdImageColorReplace
+*/
+BGD_DECLARE(int) gdImageColorReplace (gdImagePtr im, int src, int dst)
+{
+ register int x, y;
+ int n = 0;
+
+ if (src == dst) {
+ return 0;
+ }
+
+#define REPLACING_LOOP(pixel) do { \
+ for (y = im->cy1; y <= im->cy2; y++) { \
+ for (x = im->cx1; x <= im->cx2; x++) { \
+ if (pixel(im, x, y) == src) { \
+ gdImageSetPixel(im, x, y, dst); \
+ n++; \
+ } \
+ } \
+ } \
+ } while (0)
+
+ if (im->trueColor) {
+ REPLACING_LOOP(gdImageTrueColorPixel);
+ } else {
+ REPLACING_LOOP(gdImagePalettePixel);
+ }
+
+#undef REPLACING_LOOP
+
+ return n;
+}
+
+/*
+ Function: gdImageColorReplaceThreshold
+*/
+BGD_DECLARE(int) gdImageColorReplaceThreshold (gdImagePtr im, int src, int dst, float threshold)
+{
+ register int x, y;
+ int n = 0;
+
+ if (src == dst) {
+ return 0;
+ }
+
+#define REPLACING_LOOP(pixel) do { \
+ for (y = im->cy1; y <= im->cy2; y++) { \
+ for (x = im->cx1; x <= im->cx2; x++) { \
+ if (gdColorMatch(im, src, pixel(im, x, y), threshold)) { \
+ gdImageSetPixel(im, x, y, dst); \
+ n++; \
+ } \
+ } \
+ } \
+ } while (0)
+
+ if (im->trueColor) {
+ REPLACING_LOOP(gdImageTrueColorPixel);
+ } else {
+ REPLACING_LOOP(gdImagePalettePixel);
+ }
+
+#undef REPLACING_LOOP
+
+ return n;
+}
+
+static int colorCmp (const void *x, const void *y)
+{
+ int a = *(int const *)x;
+ int b = *(int const *)y;
+ return (a > b) - (a < b);
+}
+
+/*
+ Function: gdImageColorReplaceArray
+*/
+BGD_DECLARE(int) gdImageColorReplaceArray (gdImagePtr im, int len, int *src, int *dst)
+{
+ register int x, y;
+ int c, *d, *base;
+ int i, n = 0;
+
+ if (len <= 0 || src == dst) {
+ return 0;
+ }
+ if (len == 1) {
+ return gdImageColorReplace(im, src[0], dst[0]);
+ }
+ if (overflow2(len, sizeof(int)<<1)) {
+ return -1;
+ }
+ base = (int *)gdMalloc(len * (sizeof(int)<<1));
+ if (!base) {
+ return -1;
+ }
+ for (i = 0; i < len; i++) {
+ base[(i<<1)] = src[i];
+ base[(i<<1)+1] = dst[i];
+ }
+ qsort(base, len, sizeof(int)<<1, colorCmp);
+
+#define REPLACING_LOOP(pixel) do { \
+ for (y = im->cy1; y <= im->cy2; y++) { \
+ for (x = im->cx1; x <= im->cx2; x++) { \
+ c = pixel(im, x, y); \
+ if ( (d = (int *)bsearch(&c, base, len, sizeof(int)<<1, colorCmp)) ) { \
+ gdImageSetPixel(im, x, y, d[1]); \
+ n++; \
+ } \
+ } \
+ } \
+ } while (0)
+
+ if (im->trueColor) {
+ REPLACING_LOOP(gdImageTrueColorPixel);
+ } else {
+ REPLACING_LOOP(gdImagePalettePixel);
+ }
+
+#undef REPLACING_LOOP
+
+ gdFree(base);
+ return n;
+}
+
+/*
+ Function: gdImageColorReplaceCallback
+*/
+BGD_DECLARE(int) gdImageColorReplaceCallback (gdImagePtr im, gdCallbackImageColor callback)
+{
+ int c, d, n = 0;
+
+ if (!callback) {
+ return 0;
+ }
+ if (im->trueColor) {
+ register int x, y;
+
+ for (y = im->cy1; y <= im->cy2; y++) {
+ for (x = im->cx1; x <= im->cx2; x++) {
+ c = gdImageTrueColorPixel(im, x, y);
+ if ( (d = callback(im, c)) != c) {
+ gdImageSetPixel(im, x, y, d);
+ n++;
+ }
+ }
+ }
+ } else { /* palette */
+ int *sarr, *darr;
+ int k, len = 0;
+
+ sarr = (int *)gdCalloc(im->colorsTotal, sizeof(int));
+ if (!sarr) {
+ return -1;
+ }
+ for (c = 0; c < im->colorsTotal; c++) {
+ if (!im->open[c]) {
+ sarr[len++] = c;
+ }
+ }
+ darr = (int *)gdCalloc(len, sizeof(int));
+ if (!darr) {
+ gdFree(sarr);
+ return -1;
+ }
+ for (k = 0; k < len; k++) {
+ darr[k] = callback(im, sarr[k]);
+ }
+ n = gdImageColorReplaceArray(im, k, sarr, darr);
+ gdFree(darr);
+ gdFree(sarr);
+ }
+ return n;
+}
+
+/* 2.0.10: before the drawing routines, some code to clip points that are
+ * outside the drawing window. Nick Atty (nick@canalplan.org.uk)
+ *
+ * This is the Sutherland Hodgman Algorithm, as implemented by
+ * Duvanenko, Robbins and Gyurcsik - SH(DRG) for short. See Dr Dobb's
+ * Journal, January 1996, pp107-110 and 116-117
+ *
+ * Given the end points of a line, and a bounding rectangle (which we
+ * know to be from (0,0) to (SX,SY)), adjust the endpoints to be on
+ * the edges of the rectangle if the line should be drawn at all,
+ * otherwise return a failure code */
+
+/* this does "one-dimensional" clipping: note that the second time it
+ is called, all the x parameters refer to height and the y to width
+ - the comments ignore this (if you can understand it when it's
+ looking at the X parameters, it should become clear what happens on
+ the second call!) The code is simplified from that in the article,
+ as we know that gd images always start at (0,0) */
+
+/* 2.0.26, TBB: we now have to respect a clipping rectangle, it won't
+ necessarily start at 0. */
+
+static int
+clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
+{
+ double m; /* gradient of line */
+ if (*x0 < mindim) {
+ /* start of line is left of window */
+ if (*x1 < mindim) /* as is the end, so the line never cuts the window */
+ return 0;
+ m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
+ /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
+ *y0 -= (int)(m * (*x0 - mindim));
+ *x0 = mindim;
+ /* now, perhaps, adjust the far end of the line as well */
+ if (*x1 > maxdim) {
+ *y1 += m * (maxdim - *x1);
+ *x1 = maxdim;
+ }
+ return 1;
+ }
+ if (*x0 > maxdim) {
+ /* start of line is right of window -
+ complement of above */
+ if (*x1 > maxdim) /* as is the end, so the line misses the window */
+ return 0;
+ m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
+ *y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right
+ boundary */
+ *x0 = maxdim;
+ /* now, perhaps, adjust the end of the line */
+ if (*x1 < mindim) {
+ *y1 -= (int)(m * (*x1 - mindim));
+ *x1 = mindim;
+ }
+ return 1;
+ }
+ /* the final case - the start of the line is inside the window */
+ if (*x1 > maxdim) {
+ /* other end is outside to the right */
+ m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
+ *y1 += (int)(m * (maxdim - *x1));
+ *x1 = maxdim;
+ return 1;
+ }
+ if (*x1 < mindim) {
+ /* other end is outside to the left */
+ m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
+ *y1 -= (int)(m * (*x1 - mindim));
+ *x1 = mindim;
+ return 1;
+ }
+ /* only get here if both points are inside the window */
+ return 1;
+}
+
+/* end of line clipping code */
+
+/**
+ * Group: Pixels
+ */
+
+/*
+ Function: gdImageSetPixel
+*/
+BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color)
+{
+ int p;
+ switch (color) {
+ case gdStyled:
+ if (!im->style) {
+ /* Refuse to draw if no style is set. */
+ return;
+ } else {
+ p = im->style[im->stylePos++];
+ }
+ if (p != (gdTransparent)) {
+ gdImageSetPixel (im, x, y, p);
+ }
+ im->stylePos = im->stylePos % im->styleLength;
+ break;
+ case gdStyledBrushed:
+ if (!im->style) {
+ /* Refuse to draw if no style is set. */
+ return;
+ }
+ p = im->style[im->stylePos++];
+ if ((p != gdTransparent) && (p != 0)) {
+ gdImageSetPixel (im, x, y, gdBrushed);
+ }
+ im->stylePos = im->stylePos % im->styleLength;
+ break;
+ case gdBrushed:
+ gdImageBrushApply (im, x, y);
+ break;
+ case gdTiled:
+ gdImageTileApply (im, x, y);
+ break;
+ case gdAntiAliased:
+ /* This shouldn't happen (2.0.26) because we just call
+ gdImageAALine now, but do something sane. */
+ gdImageSetPixel(im, x, y, im->AA_color);
+ break;
+ default:
+ if (gdImageBoundsSafeMacro (im, x, y)) {
+ if (im->trueColor) {
+ switch (im->alphaBlendingFlag) {
+ default:
+ case gdEffectReplace:
+ im->tpixels[y][x] = color;
+ break;
+ case gdEffectAlphaBlend:
+ case gdEffectNormal:
+ im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
+ break;
+ case gdEffectOverlay :
+ im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color);
+ break;
+ case gdEffectMultiply :
+ im->tpixels[y][x] = gdLayerMultiply(im->tpixels[y][x], color);
+ break;
+ }
+ } else {
+ im->pixels[y][x] = color;
+ }
+ }
+ break;
+ }
+}
+
+static void
+gdImageBrushApply (gdImagePtr im, int x, int y)
+{
+ int lx, ly;
+ int hy;
+ int hx;
+ int x1, y1, x2, y2;
+ int srcx, srcy;
+ if (!im->brush) {
+ return;
+ }
+ hy = gdImageSY (im->brush) / 2;
+ y1 = y - hy;
+ y2 = y1 + gdImageSY (im->brush);
+ hx = gdImageSX (im->brush) / 2;
+ x1 = x - hx;
+ x2 = x1 + gdImageSX (im->brush);
+ srcy = 0;
+ if (im->trueColor) {
+ if (im->brush->trueColor) {
+ for (ly = y1; (ly < y2); ly++) {
+ srcx = 0;
+ for (lx = x1; (lx < x2); lx++) {
+ int p;
+ p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
+ /* 2.0.9, Thomas Winzig: apply simple full transparency */
+ if (p != gdImageGetTransparent (im->brush)) {
+ gdImageSetPixel (im, lx, ly, p);
+ }
+ srcx++;
+ }
+ srcy++;
+ }
+ } else {
+ /* 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger
+ for pointing out the issue) */
+ for (ly = y1; (ly < y2); ly++) {
+ srcx = 0;
+ for (lx = x1; (lx < x2); lx++) {
+ int p, tc;
+ p = gdImageGetPixel (im->brush, srcx, srcy);
+ tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
+ /* 2.0.9, Thomas Winzig: apply simple full transparency */
+ if (p != gdImageGetTransparent (im->brush)) {
+ gdImageSetPixel (im, lx, ly, tc);
+ }
+ srcx++;
+ }
+ srcy++;
+ }
+ }
+ } else {
+ for (ly = y1; (ly < y2); ly++) {
+ srcx = 0;
+ for (lx = x1; (lx < x2); lx++) {
+ int p;
+ p = gdImageGetPixel (im->brush, srcx, srcy);
+ /* Allow for non-square brushes! */
+ if (p != gdImageGetTransparent (im->brush)) {
+ /* Truecolor brush. Very slow
+ on a palette destination. */
+ if (im->brush->trueColor) {
+ gdImageSetPixel (im, lx, ly,
+ gdImageColorResolveAlpha (im,
+ gdTrueColorGetRed
+ (p),
+ gdTrueColorGetGreen
+ (p),
+ gdTrueColorGetBlue
+ (p),
+ gdTrueColorGetAlpha
+ (p)));
+ } else {
+ gdImageSetPixel (im, lx, ly, im->brushColorMap[p]);
+ }
+ }
+ srcx++;
+ }
+ srcy++;
+ }
+ }
+}
+
+static void
+gdImageTileApply (gdImagePtr im, int x, int y)
+{
+ gdImagePtr tile = im->tile;
+ int srcx, srcy;
+ int p;
+ if (!tile) {
+ return;
+ }
+ srcx = x % gdImageSX (tile);
+ srcy = y % gdImageSY (tile);
+ if (im->trueColor) {
+ p = gdImageGetPixel (tile, srcx, srcy);
+ if (p != gdImageGetTransparent (tile)) {
+ if (!tile->trueColor) {
+ p = gdTrueColorAlpha(tile->red[p], tile->green[p], tile->blue[p], tile->alpha[p]);
+ }
+ gdImageSetPixel (im, x, y, p);
+ }
+ } else {
+ p = gdImageGetPixel (tile, srcx, srcy);
+ /* Allow for transparency */
+ if (p != gdImageGetTransparent (tile)) {
+ if (tile->trueColor) {
+ /* Truecolor tile. Very slow
+ on a palette destination. */
+ gdImageSetPixel (im, x, y,
+ gdImageColorResolveAlpha (im,
+ gdTrueColorGetRed
+ (p),
+ gdTrueColorGetGreen
+ (p),
+ gdTrueColorGetBlue
+ (p),
+ gdTrueColorGetAlpha
+ (p)));
+ } else {
+ gdImageSetPixel (im, x, y, im->tileColorMap[p]);
+ }
+ }
+ }
+}
+
+/**
+ * Function: gdImageGetPixel
+ *
+ * Gets a pixel color as stored in the image.
+ *
+ * Parameters:
+ * im - The image.
+ * x - The x-coordinate.
+ * y - The y-coordinate.
+ *
+ * See also:
+ * - <gdImageGetTrueColorPixel>
+ * - <gdImagePalettePixel>
+ * - <gdImageTrueColorPixel>
+ */
+BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y)
+{
+ if (gdImageBoundsSafeMacro (im, x, y)) {
+ if (im->trueColor) {
+ return im->tpixels[y][x];
+ } else {
+ return im->pixels[y][x];
+ }
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Function: gdImageGetTrueColorPixel
+ *
+ * Gets a pixel color always as truecolor value.
+ *
+ * Parameters:
+ * im - The image.
+ * x - The x-coordinate.
+ * y - The y-coordinate.
+ *
+ * See also:
+ * - <gdImageGetPixel>
+ * - <gdImageTrueColorPixel>
+ */
+BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
+{
+ int p = gdImageGetPixel (im, x, y);
+ if (!im->trueColor) {
+ return gdTrueColorAlpha (im->red[p], im->green[p], im->blue[p],
+ (im->transparent == p) ? gdAlphaTransparent :
+ im->alpha[p]);
+ } else {
+ return p;
+ }
+}
+
+/**
+ * Group: Primitives
+ */
+
+/*
+ Function: gdImageAABlend
+
+ NO-OP, kept for library compatibility.
+*/
+BGD_DECLARE(void) gdImageAABlend (gdImagePtr im)
+{
+ (void)im;
+}
+
+static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col);
+
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color);
+
+static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col)
+{
+ if (im->thick > 1) {
+ int thickhalf = im->thick >> 1;
+ _gdImageFilledHRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
+ } else {
+ if (x2 < x1) {
+ int t = x2;
+ x2 = x1;
+ x1 = t;
+ }
+
+ for (; x1 <= x2; x1++) {
+ gdImageSetPixel(im, x1, y, col);
+ }
+ }
+ return;
+}
+
+static void gdImageVLine(gdImagePtr im, int x, int y1, int y2, int col)
+{
+ if (im->thick > 1) {
+ int thickhalf = im->thick >> 1;
+ gdImageFilledRectangle(im, x - thickhalf, y1, x + im->thick - thickhalf - 1, y2, col);
+ } else {
+ if (y2 < y1) {
+ int t = y1;
+ y1 = y2;
+ y2 = t;
+ }
+
+ for (; y1 <= y2; y1++) {
+ gdImageSetPixel(im, x, y1, col);
+ }
+ }
+ return;
+}
+
+/*
+ Function: gdImageLine
+
+ Bresenham as presented in Foley & Van Dam.
+*/
+BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int wid;
+ int w, wstart;
+ int thick;
+
+ if (color == gdAntiAliased) {
+ /*
+ gdAntiAliased passed as color: use the much faster, much cheaper
+ and equally attractive gdImageAALine implementation. That
+ clips too, so don't clip twice.
+ */
+ gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
+ return;
+ }
+ /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
+ points need to be drawn. 2.0.26, TBB: clip to edges of clipping
+ rectangle. We were getting away with this because gdImageSetPixel
+ is used for actual drawing, but this is still more efficient and opens
+ the way to skip per-pixel bounds checking in the future. */
+
+ if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
+ return;
+ if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
+ return;
+ thick = im->thick;
+
+ dx = abs (x2 - x1);
+ dy = abs (y2 - y1);
+
+ if (dx == 0) {
+ gdImageVLine(im, x1, y1, y2, color);
+ return;
+ } else if (dy == 0) {
+ gdImageHLine(im, y1, x1, x2, color);
+ return;
+ }
+
+ if (dy <= dx) {
+ /* More-or-less horizontal. use wid for vertical stroke */
+ /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
+
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double ac = cos (atan2 (dy, dx));
+ if (ac != 0) {
+ wid = thick / ac;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0) {
+ wid = 1;
+ }
+ d = 2 * dy - dx;
+ incr1 = 2 * dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+
+ /* Set up line thickness */
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, x, w, color);
+
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y++;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, x, w, color);
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y--;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, x, w, color);
+ }
+ }
+ } else {
+ /* More-or-less vertical. use wid for horizontal stroke */
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double as = sin (atan2 (dy, dx));
+ if (as != 0) {
+ wid = thick / as;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0)
+ wid = 1;
+
+ d = 2 * dx - dy;
+ incr1 = 2 * dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+
+ /* Set up line thickness */
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, w, y, color);
+
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x++;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, w, y, color);
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x--;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, w, y, color);
+ }
+ }
+ }
+
+}
+static void dashedSet (gdImagePtr im, int x, int y, int color,
+ int *onP, int *dashStepP, int wid, int vert);
+
+/*
+ Function: gdImageDashedLine
+*/
+BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int dashStep = 0;
+ int on = 1;
+ int wid;
+ int vert;
+ int thick = im->thick;
+
+ dx = abs (x2 - x1);
+ dy = abs (y2 - y1);
+ if (dy <= dx) {
+ /* More-or-less horizontal. use wid for vertical stroke */
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double as = sin (atan2 (dy, dx));
+ if (as != 0) {
+ wid = thick / as;
+ } else {
+ wid = 1;
+ }
+ vert = 1;
+
+ d = 2 * dy - dx;
+ incr1 = 2 * dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y++;
+ d += incr2;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y--;
+ d += incr2;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ }
+ }
+ } else {
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double as = sin (atan2 (dy, dx));
+ if (as != 0) {
+ wid = thick / as;
+ } else {
+ wid = 1;
+ }
+ vert = 0;
+
+ d = 2 * dx - dy;
+ incr1 = 2 * dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x++;
+ d += incr2;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x--;
+ d += incr2;
+ }
+ dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
+ }
+ }
+ }
+}
+
+static void
+dashedSet (gdImagePtr im, int x, int y, int color,
+ int *onP, int *dashStepP, int wid, int vert)
+{
+ int dashStep = *dashStepP;
+ int on = *onP;
+ int w, wstart;
+
+ dashStep++;
+ if (dashStep == gdDashSize) {
+ dashStep = 0;
+ on = !on;
+ }
+ if (on) {
+ if (vert) {
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, x, w, color);
+ } else {
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ gdImageSetPixel (im, w, y, color);
+ }
+ }
+ *dashStepP = dashStep;
+ *onP = on;
+}
+
+/*
+ Function: gdImageBoundsSafe
+*/
+BGD_DECLARE(int) gdImageBoundsSafe (gdImagePtr im, int x, int y)
+{
+ return gdImageBoundsSafeMacro (im, x, y);
+}
+
+/**
+ * Function: gdImageChar
+ *
+ * Draws a single character.
+ *
+ * Parameters:
+ * im - The image to draw onto.
+ * f - The raster font.
+ * x - The x coordinate of the upper left pixel.
+ * y - The y coordinate of the upper left pixel.
+ * c - The character.
+ * color - The color.
+ *
+ * Variants:
+ * - <gdImageCharUp>
+ *
+ * See also:
+ * - <gdFontPtr>
+ */
+BGD_DECLARE(void) gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
+{
+ int cx, cy;
+ int px, py;
+ int fline;
+ cx = 0;
+ cy = 0;
+#ifdef CHARSET_EBCDIC
+ c = ASC (c);
+#endif /*CHARSET_EBCDIC */
+ if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
+ return;
+ }
+ fline = (c - f->offset) * f->h * f->w;
+ for (py = y; (py < (y + f->h)); py++) {
+ for (px = x; (px < (x + f->w)); px++) {
+ if (f->data[fline + cy * f->w + cx]) {
+ gdImageSetPixel (im, px, py, color);
+ }
+ cx++;
+ }
+ cx = 0;
+ cy++;
+ }
+}
+
+/**
+ * Function: gdImageCharUp
+ */
+BGD_DECLARE(void) gdImageCharUp (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
+{
+ int cx, cy;
+ int px, py;
+ int fline;
+ cx = 0;
+ cy = 0;
+#ifdef CHARSET_EBCDIC
+ c = ASC (c);
+#endif /*CHARSET_EBCDIC */
+ if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
+ return;
+ }
+ fline = (c - f->offset) * f->h * f->w;
+ for (py = y; (py > (y - f->w)); py--) {
+ for (px = x; (px < (x + f->h)); px++) {
+ if (f->data[fline + cy * f->w + cx]) {
+ gdImageSetPixel (im, px, py, color);
+ }
+ cy++;
+ }
+ cy = 0;
+ cx++;
+ }
+}
+
+/**
+ * Function: gdImageString
+ *
+ * Draws a character string.
+ *
+ * Parameters:
+ * im - The image to draw onto.
+ * f - The raster font.
+ * x - The x coordinate of the upper left pixel.
+ * y - The y coordinate of the upper left pixel.
+ * c - The character string.
+ * color - The color.
+ *
+ * Variants:
+ * - <gdImageStringUp>
+ * - <gdImageString16>
+ * - <gdImageStringUp16>
+ *
+ * See also:
+ * - <gdFontPtr>
+ * - <gdImageStringTTF>
+ */
+BGD_DECLARE(void) gdImageString (gdImagePtr im, gdFontPtr f,
+ int x, int y, unsigned char *s, int color)
+{
+ int i;
+ int l;
+ l = strlen ((char *) s);
+ for (i = 0; (i < l); i++) {
+ gdImageChar (im, f, x, y, s[i], color);
+ x += f->w;
+ }
+}
+
+/**
+ * Function: gdImageStringUp
+ */
+BGD_DECLARE(void) gdImageStringUp (gdImagePtr im, gdFontPtr f,
+ int x, int y, unsigned char *s, int color)
+{
+ int i;
+ int l;
+ l = strlen ((char *) s);
+ for (i = 0; (i < l); i++) {
+ gdImageCharUp (im, f, x, y, s[i], color);
+ y -= f->w;
+ }
+}
+
+static int strlen16 (unsigned short *s);
+
+/**
+ * Function: gdImageString16
+ */
+BGD_DECLARE(void) gdImageString16 (gdImagePtr im, gdFontPtr f,
+ int x, int y, unsigned short *s, int color)
+{
+ int i;
+ int l;
+ l = strlen16 (s);
+ for (i = 0; (i < l); i++) {
+ gdImageChar (im, f, x, y, s[i], color);
+ x += f->w;
+ }
+}
+
+/**
+ * Function: gdImageStringUp16
+ */
+BGD_DECLARE(void) gdImageStringUp16 (gdImagePtr im, gdFontPtr f,
+ int x, int y, unsigned short *s, int color)
+{
+ int i;
+ int l;
+ l = strlen16 (s);
+ for (i = 0; (i < l); i++) {
+ gdImageCharUp (im, f, x, y, s[i], color);
+ y -= f->w;
+ }
+}
+
+static int
+strlen16 (unsigned short *s)
+{
+ int len = 0;
+ while (*s) {
+ s++;
+ len++;
+ }
+ return len;
+}
+
+#ifndef HAVE_LSQRT
+/* If you don't have a nice square root function for longs, you can use
+ ** this hack
+ */
+long
+lsqrt (long n)
+{
+ long result = (long) sqrt ((double) n);
+ return result;
+}
+#endif
+
+/* s and e are integers modulo 360 (degrees), with 0 degrees
+ being the rightmost extreme and degrees changing clockwise.
+ cx and cy are the center in pixels; w and h are the horizontal
+ and vertical diameter in pixels. */
+
+/*
+ Function: gdImageArc
+*/
+BGD_DECLARE(void) gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
+ int color)
+{
+ gdImageFilledArc (im, cx, cy, w, h, s, e, color, gdNoFill);
+}
+
+/*
+ Function: gdImageFilledArc
+*/
+BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
+ int color, int style)
+{
+ gdPoint pts[363];
+ int i, pti;
+ int lx = 0, ly = 0;
+ int fx = 0, fy = 0;
+
+ if ((s % 360) == (e % 360)) {
+ s = 0;
+ e = 360;
+ } else {
+ if (s > 360) {
+ s = s % 360;
+ }
+
+ if (e > 360) {
+ e = e % 360;
+ }
+
+ while (s < 0) {
+ s += 360;
+ }
+
+ while (e < s) {
+ e += 360;
+ }
+
+ if (s == e) {
+ s = 0;
+ e = 360;
+ }
+ }
+
+ for (i = s, pti = 1; (i <= e); i++, pti++) {
+ int x, y;
+ x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
+ y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
+ if (i != s) {
+ if (!(style & gdChord)) {
+ if (style & gdNoFill) {
+ gdImageLine (im, lx, ly, x, y, color);
+ } else {
+ if (y == ly) {
+ pti--; /* don't add this point */
+ if (((i > 270 || i < 90) && x > lx) || ((i > 90 && i < 270) && x < lx)) {
+ /* replace the old x coord, if increasing on the
+ right side or decreasing on the left side */
+ pts[pti].x = x;
+ }
+ } else {
+ pts[pti].x = x;
+ pts[pti].y = y;
+ }
+ }
+ }
+ } else {
+ fx = x;
+ fy = y;
+
+ if (!(style & (gdChord | gdNoFill))) {
+ pts[0].x = cx;
+ pts[0].y = cy;
+ pts[pti].x = x;
+ pts[pti].y = y;
+ }
+ }
+ lx = x;
+ ly = y;
+ }
+ if (style & gdChord) {
+ if (style & gdNoFill) {
+ if (style & gdEdged) {
+ gdImageLine (im, cx, cy, lx, ly, color);
+ gdImageLine (im, cx, cy, fx, fy, color);
+ }
+ gdImageLine (im, fx, fy, lx, ly, color);
+ } else {
+ pts[0].x = fx;
+ pts[0].y = fy;
+ pts[1].x = lx;
+ pts[1].y = ly;
+ pts[2].x = cx;
+ pts[2].y = cy;
+ gdImageFilledPolygon (im, pts, 3, color);
+ }
+ } else {
+ if (style & gdNoFill) {
+ if (style & gdEdged) {
+ gdImageLine (im, cx, cy, lx, ly, color);
+ gdImageLine (im, cx, cy, fx, fy, color);
+ }
+ } else {
+ pts[pti].x = cx;
+ pts[pti].y = cy;
+ gdImageFilledPolygon(im, pts, pti+1, color);
+ }
+ }
+}
+
+/*
+ Function: gdImageEllipse
+*/
+BGD_DECLARE(void) gdImageEllipse(gdImagePtr im, int mx, int my, int w, int h, int c)
+{
+ int x=0,mx1=0,mx2=0,my1=0,my2=0;
+ long aq,bq,dx,dy,r,rx,ry,a,b;
+
+ a=w>>1;
+ b=h>>1;
+ gdImageSetPixel(im,mx+a, my, c);
+ gdImageSetPixel(im,mx-a, my, c);
+ mx1 = mx-a;
+ my1 = my;
+ mx2 = mx+a;
+ my2 = my;
+
+ aq = a * a;
+ bq = b * b;
+ dx = aq << 1;
+ dy = bq << 1;
+ r = a * bq;
+ rx = r << 1;
+ ry = 0;
+ x = a;
+ while (x > 0) {
+ if (r > 0) {
+ my1++;
+ my2--;
+ ry +=dx;
+ r -=ry;
+ }
+ if (r <= 0) {
+ x--;
+ mx1++;
+ mx2--;
+ rx -=dy;
+ r +=rx;
+ }
+ gdImageSetPixel(im,mx1, my1, c);
+ gdImageSetPixel(im,mx1, my2, c);
+ gdImageSetPixel(im,mx2, my1, c);
+ gdImageSetPixel(im,mx2, my2, c);
+ }
+}
+
+
+/*
+ Function: gdImageFilledEllipse
+*/
+BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c)
+{
+ int x=0,mx1=0,mx2=0,my1=0,my2=0;
+ long aq,bq,dx,dy,r,rx,ry,a,b;
+ int i;
+ int old_y2;
+
+ a=w>>1;
+ b=h>>1;
+
+ for (x = mx-a; x <= mx+a; x++) {
+ gdImageSetPixel(im, x, my, c);
+ }
+
+ mx1 = mx-a;
+ my1 = my;
+ mx2 = mx+a;
+ my2 = my;
+
+ aq = a * a;
+ bq = b * b;
+ dx = aq << 1;
+ dy = bq << 1;
+ r = a * bq;
+ rx = r << 1;
+ ry = 0;
+ x = a;
+ old_y2=-2;
+ while (x > 0) {
+ if (r > 0) {
+ my1++;
+ my2--;
+ ry +=dx;
+ r -=ry;
+ }
+ if (r <= 0) {
+ x--;
+ mx1++;
+ mx2--;
+ rx -=dy;
+ r +=rx;
+ }
+
+ if(old_y2!=my2) {
+ for(i=mx1; i<=mx2; i++) {
+ gdImageSetPixel(im,i,my2,c);
+ gdImageSetPixel(im,i,my1,c);
+ }
+ }
+ old_y2 = my2;
+ }
+}
+
+/*
+ Function: gdImageFillToBorder
+*/
+BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
+{
+ int lastBorder;
+ /* Seek left */
+ int leftLimit, rightLimit;
+ int i;
+ int restoreAlphaBleding;
+
+ if (border < 0 || color < 0) {
+ /* Refuse to fill to a non-solid border */
+ return;
+ }
+
+ if (!im->trueColor) {
+ if ((color > (im->colorsTotal - 1)) || (border > (im->colorsTotal - 1)) || (color < 0)) {
+ return;
+ }
+ }
+
+ leftLimit = (-1);
+
+ restoreAlphaBleding = im->alphaBlendingFlag;
+ im->alphaBlendingFlag = 0;
+
+ if (x >= im->sx) {
+ x = im->sx - 1;
+ } else if (x < 0) {
+ x = 0;
+ }
+ if (y >= im->sy) {
+ y = im->sy - 1;
+ } else if (y < 0) {
+ y = 0;
+ }
+
+ for (i = x; (i >= 0); i--) {
+ if (gdImageGetPixel (im, i, y) == border) {
+ break;
+ }
+ gdImageSetPixel (im, i, y, color);
+ leftLimit = i;
+ }
+ if (leftLimit == (-1)) {
+ im->alphaBlendingFlag = restoreAlphaBleding;
+ return;
+ }
+ /* Seek right */
+ rightLimit = x;
+ for (i = (x + 1); (i < im->sx); i++) {
+ if (gdImageGetPixel (im, i, y) == border) {
+ break;
+ }
+ gdImageSetPixel (im, i, y, color);
+ rightLimit = i;
+ }
+ /* Look at lines above and below and start paints */
+ /* Above */
+ if (y > 0) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c;
+ c = gdImageGetPixel (im, i, y - 1);
+ if (lastBorder) {
+ if ((c != border) && (c != color)) {
+ gdImageFillToBorder (im, i, y - 1, border, color);
+ lastBorder = 0;
+ }
+ } else if ((c == border) || (c == color)) {
+ lastBorder = 1;
+ }
+ }
+ }
+ /* Below */
+ if (y < ((im->sy) - 1)) {
+ lastBorder = 1;
+ for (i = leftLimit; (i <= rightLimit); i++) {
+ int c = gdImageGetPixel (im, i, y + 1);
+ if (lastBorder) {
+ if ((c != border) && (c != color)) {
+ gdImageFillToBorder (im, i, y + 1, border, color);
+ lastBorder = 0;
+ }
+ } else if ((c == border) || (c == color)) {
+ lastBorder = 1;
+ }
+ }
+ }
+ im->alphaBlendingFlag = restoreAlphaBleding;
+}
+
+/*
+ * set the pixel at (x,y) and its 4-connected neighbors
+ * with the same pixel value to the new pixel value nc (new color).
+ * A 4-connected neighbor: pixel above, below, left, or right of a pixel.
+ * ideas from comp.graphics discussions.
+ * For tiled fill, the use of a flag buffer is mandatory. As the tile image can
+ * contain the same color as the color to fill. To do not bloat normal filling
+ * code I added a 2nd private function.
+ */
+
+static int gdImageTileGet (gdImagePtr im, int x, int y)
+{
+ int srcx, srcy;
+ int tileColor,p;
+ if (!im->tile) {
+ return -1;
+ }
+ srcx = x % gdImageSX(im->tile);
+ srcy = y % gdImageSY(im->tile);
+ p = gdImageGetPixel(im->tile, srcx, srcy);
+ if (p == im->tile->transparent) {
+ tileColor = im->transparent;
+ } else if (im->trueColor) {
+ if (im->tile->trueColor) {
+ tileColor = p;
+ } else {
+ tileColor = gdTrueColorAlpha( gdImageRed(im->tile,p), gdImageGreen(im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
+ }
+ } else {
+ if (im->tile->trueColor) {
+ tileColor = gdImageColorResolveAlpha(im, gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p));
+ } else {
+ tileColor = gdImageColorResolveAlpha(im, gdImageRed (im->tile,p), gdImageGreen (im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
+ }
+ }
+ return tileColor;
+}
+
+
+
+/* horizontal segment of scan line y */
+struct seg {
+ int y, xl, xr, dy;
+};
+
+/* max depth of stack */
+#define FILL_MAX ((int)(im->sy*im->sx)/4)
+#define FILL_PUSH(Y, XL, XR, DY) \
+ if (sp<stack+FILL_MAX && Y+(DY)>=0 && Y+(DY)<wy2) \
+ {sp->y = Y; sp->xl = XL; sp->xr = XR; sp->dy = DY; sp++;}
+
+#define FILL_POP(Y, XL, XR, DY) \
+ {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;}
+
+static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc);
+
+/*
+ Function: gdImageFill
+*/
+BGD_DECLARE(void) gdImageFill(gdImagePtr im, int x, int y, int nc)
+{
+ int l, x1, x2, dy;
+ int oc; /* old pixel value */
+ int wx2,wy2;
+
+ int alphablending_bak;
+
+ /* stack of filled segments */
+ /* struct seg stack[FILL_MAX],*sp = stack; */
+ struct seg *stack;
+ struct seg *sp;
+
+ if (!im->trueColor && nc > (im->colorsTotal - 1)) {
+ return;
+ }
+
+ alphablending_bak = im->alphaBlendingFlag;
+ im->alphaBlendingFlag = 0;
+
+ if (nc==gdTiled) {
+ _gdImageFillTiled(im,x,y,nc);
+ im->alphaBlendingFlag = alphablending_bak;
+ return;
+ }
+
+ wx2=im->sx;
+ wy2=im->sy;
+ oc = gdImageGetPixel(im, x, y);
+ if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
+ im->alphaBlendingFlag = alphablending_bak;
+ return;
+ }
+
+ /* Do not use the 4 neighbors implementation with
+ * small images
+ */
+ if (im->sx < 4) {
+ int ix = x, iy = y, c;
+ do {
+ do {
+ c = gdImageGetPixel(im, ix, iy);
+ if (c != oc) {
+ goto done;
+ }
+ gdImageSetPixel(im, ix, iy, nc);
+ } while(ix++ < (im->sx -1));
+ ix = x;
+ } while(iy++ < (im->sy -1));
+ goto done;
+ }
+
+ if(overflow2(im->sy, im->sx)) {
+ return;
+ }
+
+ if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) {
+ return;
+ }
+
+ stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
+ if (!stack) {
+ return;
+ }
+ sp = stack;
+
+ /* required! */
+ FILL_PUSH(y,x,x,1);
+ /* seed segment (popped 1st) */
+ FILL_PUSH(y+1, x, x, -1);
+ while (sp>stack) {
+ FILL_POP(y, x1, x2, dy);
+
+ for (x=x1; x>=0 && gdImageGetPixel(im,x, y)==oc; x--) {
+ gdImageSetPixel(im,x, y, nc);
+ }
+ if (x>=x1) {
+ goto skip;
+ }
+ l = x+1;
+
+ /* leak on left? */
+ if (l<x1) {
+ FILL_PUSH(y, l, x1-1, -dy);
+ }
+ x = x1+1;
+ do {
+ for (; x<=wx2 && gdImageGetPixel(im,x, y)==oc; x++) {
+ gdImageSetPixel(im, x, y, nc);
+ }
+ FILL_PUSH(y, l, x-1, dy);
+ /* leak on right? */
+ if (x>x2+1) {
+ FILL_PUSH(y, x2+1, x-1, -dy);
+ }
+skip:
+ for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);
+
+ l = x;
+ } while (x<=x2);
+ }
+
+ gdFree(stack);
+
+done:
+ im->alphaBlendingFlag = alphablending_bak;
+}
+
+static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
+{
+ int l, x1, x2, dy;
+ int oc; /* old pixel value */
+ int wx2,wy2;
+ /* stack of filled segments */
+ struct seg *stack;
+ struct seg *sp;
+ char *pts;
+
+ if (!im->tile) {
+ return;
+ }
+
+ wx2=im->sx;
+ wy2=im->sy;
+
+ if(overflow2(im->sy, im->sx)) {
+ return;
+ }
+
+ if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) {
+ return;
+ }
+
+ pts = (char *) gdCalloc(im->sy * im->sx, sizeof(char));
+ if (!pts) {
+ return;
+ }
+
+ stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
+ if (!stack) {
+ gdFree(pts);
+ return;
+ }
+ sp = stack;
+
+ oc = gdImageGetPixel(im, x, y);
+
+ /* required! */
+ FILL_PUSH(y,x,x,1);
+ /* seed segment (popped 1st) */
+ FILL_PUSH(y+1, x, x, -1);
+ while (sp>stack) {
+ FILL_POP(y, x1, x2, dy);
+ for (x=x1; x>=0 && (!pts[y + x*wy2] && gdImageGetPixel(im,x,y)==oc); x--) {
+ nc = gdImageTileGet(im,x,y);
+ pts[y + x*wy2]=1;
+ gdImageSetPixel(im,x, y, nc);
+ }
+ if (x>=x1) {
+ goto skip;
+ }
+ l = x+1;
+
+ /* leak on left? */
+ if (l<x1) {
+ FILL_PUSH(y, l, x1-1, -dy);
+ }
+ x = x1+1;
+ do {
+ for (; x<wx2 && (!pts[y + x*wy2] && gdImageGetPixel(im,x, y)==oc) ; x++) {
+ if (pts[y + x*wy2]) {
+ /* we should never be here */
+ break;
+ }
+ nc = gdImageTileGet(im,x,y);
+ pts[y + x*wy2]=1;
+ gdImageSetPixel(im, x, y, nc);
+ }
+ FILL_PUSH(y, l, x-1, dy);
+ /* leak on right? */
+ if (x>x2+1) {
+ FILL_PUSH(y, x2+1, x-1, -dy);
+ }
+skip:
+ for (x++; x<=x2 && (pts[y + x*wy2] || gdImageGetPixel(im,x, y)!=oc); x++);
+ l = x;
+ } while (x<=x2);
+ }
+
+ gdFree(pts);
+ gdFree(stack);
+}
+
+/**
+ * Function: gdImageRectangle
+ *
+ * Draws a rectangle.
+ *
+ * Parameters:
+ * im - The image.
+ * x1 - The x-coordinate of the upper left corner.
+ * y1 - The y-coordinate of the upper left corner.
+ * x2 - The x-coordinate of the lower right corner.
+ * y2 - The y-coordinate of the lower right corner.
+ * color - The color.
+ *
+ * Note that x1,y1 and x2,y2 may be swapped, i.e. the former may designate the
+ * lower right corner and the latter the upper left corner. The behavior for
+ * specifying other corners is undefined.
+ *
+ * See also:
+ * - <gdImageFilledRectangle>
+ */
+BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
+{
+ int thick = im->thick;
+
+ if (x1 == x2 && y1 == y2 && thick == 1) {
+ gdImageSetPixel(im, x1, y1, color);
+ return;
+ }
+
+ if (y2 < y1) {
+ int t;
+ t = y1;
+ y1 = y2;
+ y2 = t;
+
+ t = x1;
+ x1 = x2;
+ x2 = t;
+ }
+
+ if (thick > 1) {
+ int cx, cy, x1ul, y1ul, x2lr, y2lr;
+ int half = thick >> 1;
+ x1ul = x1 - half;
+ y1ul = y1 - half;
+
+ x2lr = x2 + half;
+ y2lr = y2 + half;
+
+ cy = y1ul + thick;
+ while (cy-- > y1ul) {
+ cx = x1ul - 1;
+ while (cx++ < x2lr) {
+ gdImageSetPixel(im, cx, cy, color);
+ }
+ }
+
+ cy = y2lr - thick;
+ while (cy++ < y2lr) {
+ cx = x1ul - 1;
+ while (cx++ < x2lr) {
+ gdImageSetPixel(im, cx, cy, color);
+ }
+ }
+
+ cy = y1ul + thick - 1;
+ while (cy++ < y2lr -thick) {
+ cx = x1ul - 1;
+ while (cx++ < x1ul + thick) {
+ gdImageSetPixel(im, cx, cy, color);
+ }
+ }
+
+ cy = y1ul + thick - 1;
+ while (cy++ < y2lr -thick) {
+ cx = x2lr - thick - 1;
+ while (cx++ < x2lr) {
+ gdImageSetPixel(im, cx, cy, color);
+ }
+ }
+
+ return;
+ } else {
+ if (x1 == x2 || y1 == y2) {
+ gdImageLine(im, x1, y1, x2, y2, color);
+ } else {
+ gdImageLine(im, x1, y1, x2, y1, color);
+ gdImageLine(im, x1, y2, x2, y2, color);
+ gdImageLine(im, x1, y1 + 1, x1, y2 - 1, color);
+ gdImageLine(im, x2, y1 + 1, x2, y2 - 1, color);
+ }
+ }
+}
+
+static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color)
+{
+ int x, y;
+
+ if (x1 == x2 && y1 == y2) {
+ gdImageSetPixel(im, x1, y1, color);
+ return;
+ }
+
+ if (x1 > x2) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+ }
+
+ if (y1 > y2) {
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+
+ if (x1 < 0) {
+ x1 = 0;
+ }
+
+ if (x2 >= gdImageSX(im)) {
+ x2 = gdImageSX(im) - 1;
+ }
+
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ if (y2 >= gdImageSY(im)) {
+ y2 = gdImageSY(im) - 1;
+ }
+
+ for (x = x1; (x <= x2); x++) {
+ for (y = y1; (y <= y2); y++) {
+ gdImageSetPixel (im, x, y, color);
+ }
+ }
+}
+
+static void _gdImageFilledVRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color)
+{
+ int x, y;
+
+ if (x1 == x2 && y1 == y2) {
+ gdImageSetPixel(im, x1, y1, color);
+ return;
+ }
+
+ if (x1 > x2) {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+ }
+
+ if (y1 > y2) {
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+
+ if (x1 < 0) {
+ x1 = 0;
+ }
+
+ if (x2 >= gdImageSX(im)) {
+ x2 = gdImageSX(im) - 1;
+ }
+
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ if (y2 >= gdImageSY(im)) {
+ y2 = gdImageSY(im) - 1;
+ }
+
+ for (y = y1; (y <= y2); y++) {
+ for (x = x1; (x <= x2); x++) {
+ gdImageSetPixel (im, x, y, color);
+ }
+ }
+}
+
+/*
+ Function: gdImageFilledRectangle
+*/
+BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color)
+{
+ _gdImageFilledVRectangle(im, x1, y1, x2, y2, color);
+}
+
+/**
+ * Group: Cloning and Copying
+ */
+
+/**
+ * Function: gdImageClone
+ *
+ * Clones an image
+ *
+ * Creates an exact duplicate of the given image.
+ *
+ * Parameters:
+ * src - The source image.
+ *
+ * Returns:
+ * The cloned image on success, NULL on failure.
+ */
+BGD_DECLARE(gdImagePtr) gdImageClone (gdImagePtr src) {
+ gdImagePtr dst;
+ register int i, x;
+
+ if (src->trueColor) {
+ dst = gdImageCreateTrueColor(src->sx , src->sy);
+ } else {
+ dst = gdImageCreate(src->sx , src->sy);
+ }
+
+ if (dst == NULL) {
+ return NULL;
+ }
+
+ if (src->trueColor == 0) {
+ dst->colorsTotal = src->colorsTotal;
+ for (i = 0; i < gdMaxColors; i++) {
+ dst->red[i] = src->red[i];
+ dst->green[i] = src->green[i];
+ dst->blue[i] = src->blue[i];
+ dst->alpha[i] = src->alpha[i];
+ dst->open[i] = src->open[i];
+ }
+ for (i = 0; i < src->sy; i++) {
+ for (x = 0; x < src->sx; x++) {
+ dst->pixels[i][x] = src->pixels[i][x];
+ }
+ }
+ } else {
+ for (i = 0; i < src->sy; i++) {
+ for (x = 0; x < src->sx; x++) {
+ dst->tpixels[i][x] = src->tpixels[i][x];
+ }
+ }
+ }
+
+ if (src->styleLength > 0) {
+ dst->styleLength = src->styleLength;
+ dst->stylePos = src->stylePos;
+ for (i = 0; i < src->styleLength; i++) {
+ dst->style[i] = src->style[i];
+ }
+ }
+
+ dst->interlace = src->interlace;
+
+ dst->alphaBlendingFlag = src->alphaBlendingFlag;
+ dst->saveAlphaFlag = src->saveAlphaFlag;
+ dst->AA = src->AA;
+ dst->AA_color = src->AA_color;
+ dst->AA_dont_blend = src->AA_dont_blend;
+
+ dst->cx1 = src->cx1;
+ dst->cy1 = src->cy1;
+ dst->cx2 = src->cx2;
+ dst->cy2 = src->cy2;
+
+ dst->res_x = src->res_x;
+ dst->res_y = src->res_y;
+
+ dst->paletteQuantizationMethod = src->paletteQuantizationMethod;
+ dst->paletteQuantizationSpeed = src->paletteQuantizationSpeed;
+ dst->paletteQuantizationMinQuality = src->paletteQuantizationMinQuality;
+ dst->paletteQuantizationMinQuality = src->paletteQuantizationMinQuality;
+
+ dst->interpolation_id = src->interpolation_id;
+ dst->interpolation = src->interpolation;
+
+ if (src->brush) {
+ dst->brush = gdImageClone(src->brush);
+ }
+
+ if (src->tile) {
+ dst->tile = gdImageClone(src->tile);
+ }
+
+ if (src->style) {
+ gdImageSetStyle(dst, src->style, src->styleLength);
+ }
+
+ for (i = 0; i < gdMaxColors; i++) {
+ dst->brushColorMap[i] = src->brushColorMap[i];
+ dst->tileColorMap[i] = src->tileColorMap[i];
+ }
+
+ if (src->polyAllocated > 0) {
+ dst->polyAllocated = src->polyAllocated;
+ for (i = 0; i < src->polyAllocated; i++) {
+ dst->polyInts[i] = src->polyInts[i];
+ }
+ }
+
+ return dst;
+}
+
+/**
+ * Function: gdImageCopy
+ *
+ * Copy an area of an image to another image
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the upper left corner to copy to.
+ * dstY - The y-coordinate of the upper left corner to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * w - The width of the area to copy.
+ * h - The height of the area to copy.
+ *
+ * See also:
+ * - <gdImageCopyMerge>
+ * - <gdImageCopyMergeGray>
+ */
+BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
+ int srcY, int w, int h)
+{
+ int c;
+ int x, y;
+ int tox, toy;
+ int i;
+ int colorMap[gdMaxColors];
+
+ if (dst->trueColor) {
+ /* 2.0: much easier when the destination is truecolor. */
+ /* 2.0.10: needs a transparent-index check that is still valid if
+ * * the source is not truecolor. Thanks to Frank Warmerdam.
+ */
+
+ if (src->trueColor) {
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y);
+ if (c != src->transparent) {
+ gdImageSetPixel (dst, dstX + x, dstY + y, c);
+ }
+ }
+ }
+ } else {
+ /* source is palette based */
+ for (y = 0; (y < h); y++) {
+ for (x = 0; (x < w); x++) {
+ int c = gdImageGetPixel (src, srcX + x, srcY + y);
+ if (c != src->transparent) {
+ gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]));
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ for (i = 0; (i < gdMaxColors); i++) {
+ colorMap[i] = (-1);
+ }
+ toy = dstY;
+ for (y = srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + w)); x++) {
+ int nc;
+ int mapTo;
+ c = gdImageGetPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == c) {
+ tox++;
+ continue;
+ }
+ /* Have we established a mapping for this color? */
+ if (src->trueColor) {
+ /* 2.05: remap to the palette available in the
+ destination image. This is slow and
+ works badly, but it beats crashing! Thanks
+ to Padhrig McCarthy. */
+ mapTo = gdImageColorResolveAlpha (dst,
+ gdTrueColorGetRed (c),
+ gdTrueColorGetGreen (c),
+ gdTrueColorGetBlue (c),
+ gdTrueColorGetAlpha (c));
+ } else if (colorMap[c] == (-1)) {
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ /* Get best match possible. This
+ function never returns error. */
+ nc = gdImageColorResolveAlpha (dst,
+ src->red[c], src->green[c],
+ src->blue[c], src->alpha[c]);
+ }
+ colorMap[c] = nc;
+ mapTo = colorMap[c];
+ } else {
+ mapTo = colorMap[c];
+ }
+ gdImageSetPixel (dst, tox, toy, mapTo);
+ tox++;
+ }
+ toy++;
+ }
+}
+
+/**
+ * Function: gdImageCopyMerge
+ *
+ * Copy an area of an image to another image ignoring alpha
+ *
+ * The source area will be copied to the destination are by merging the pixels.
+ *
+ * Note:
+ * This function is a substitute for real alpha channel operations,
+ * so it doesn't pay attention to the alpha channel.
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the upper left corner to copy to.
+ * dstY - The y-coordinate of the upper left corner to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * w - The width of the area to copy.
+ * h - The height of the area to copy.
+ * pct - The percentage in range 0..100.
+ *
+ * See also:
+ * - <gdImageCopy>
+ * - <gdImageCopyMergeGray>
+ */
+BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int w, int h, int pct)
+{
+
+ int c, dc;
+ int x, y;
+ int tox, toy;
+ int ncR, ncG, ncB;
+ toy = dstY;
+ for (y = srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + w)); x++) {
+ int nc;
+ c = gdImageGetPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == c) {
+ tox++;
+ continue;
+ }
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ dc = gdImageGetPixel (dst, tox, toy);
+
+ ncR = gdImageRed (src, c) * (pct / 100.0)
+ + gdImageRed (dst, dc) * ((100 - pct) / 100.0);
+ ncG = gdImageGreen (src, c) * (pct / 100.0)
+ + gdImageGreen (dst, dc) * ((100 - pct) / 100.0);
+ ncB = gdImageBlue (src, c) * (pct / 100.0)
+ + gdImageBlue (dst, dc) * ((100 - pct) / 100.0);
+
+ /* Find a reasonable color */
+ nc = gdImageColorResolve (dst, ncR, ncG, ncB);
+ }
+ gdImageSetPixel (dst, tox, toy, nc);
+ tox++;
+ }
+ toy++;
+ }
+}
+
+/**
+ * Function: gdImageCopyMergeGray
+ *
+ * Copy an area of an image to another image ignoring alpha
+ *
+ * The source area will be copied to the grayscaled destination area by merging
+ * the pixels.
+ *
+ * Note:
+ * This function is a substitute for real alpha channel operations,
+ * so it doesn't pay attention to the alpha channel.
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the upper left corner to copy to.
+ * dstY - The y-coordinate of the upper left corner to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * w - The width of the area to copy.
+ * h - The height of the area to copy.
+ * pct - The percentage of the source color intensity in range 0..100.
+ *
+ * See also:
+ * - <gdImageCopy>
+ * - <gdImageCopyMerge>
+ */
+BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int w, int h, int pct)
+{
+
+ int c, dc;
+ int x, y;
+ int tox, toy;
+ int ncR, ncG, ncB;
+ float g;
+ toy = dstY;
+ for (y = srcY; (y < (srcY + h)); y++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + w)); x++) {
+ int nc;
+ c = gdImageGetPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == c) {
+ tox++;
+ continue;
+ }
+ /*
+ * If it's the same image, mapping is NOT trivial since we
+ * merge with greyscale target, but if pct is 100, the grey
+ * value is not used, so it becomes trivial. pjw 2.0.12.
+ */
+ if (dst == src && pct == 100) {
+ nc = c;
+ } else {
+ dc = gdImageGetPixel (dst, tox, toy);
+ g = 0.29900 * gdImageRed(dst, dc)
+ + 0.58700 * gdImageGreen(dst, dc) + 0.11400 * gdImageBlue(dst, dc);
+
+ ncR = gdImageRed (src, c) * (pct / 100.0)
+ + g * ((100 - pct) / 100.0);
+ ncG = gdImageGreen (src, c) * (pct / 100.0)
+ + g * ((100 - pct) / 100.0);
+ ncB = gdImageBlue (src, c) * (pct / 100.0)
+ + g * ((100 - pct) / 100.0);
+
+ /* First look for an exact match */
+ nc = gdImageColorExact (dst, ncR, ncG, ncB);
+ if (nc == (-1)) {
+ /* No, so try to allocate it */
+ nc = gdImageColorAllocate (dst, ncR, ncG, ncB);
+ /* If we're out of colors, go for the
+ closest color */
+ if (nc == (-1)) {
+ nc = gdImageColorClosest (dst, ncR, ncG, ncB);
+ }
+ }
+ }
+ gdImageSetPixel (dst, tox, toy, nc);
+ tox++;
+ }
+ toy++;
+ }
+}
+
+/**
+ * Function: gdImageCopyResized
+ *
+ * Copy a resized area from an image to another image
+ *
+ * If the source and destination area differ in size, the area will be resized
+ * using nearest-neighbor interpolation.
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the upper left corner to copy to.
+ * dstY - The y-coordinate of the upper left corner to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * dstW - The width of the area to copy to.
+ * dstH - The height of the area to copy to.
+ * srcW - The width of the area to copy from.
+ * srcH - The height of the area to copy from.
+ *
+ * See also:
+ * - <gdImageCopyResampled>
+ * - <gdImageScale>
+ */
+BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int dstW, int dstH, int srcW,
+ int srcH)
+{
+ int c;
+ int x, y;
+ int tox, toy;
+ int ydest;
+ int i;
+ int colorMap[gdMaxColors];
+ /* Stretch vectors */
+ int *stx;
+ int *sty;
+ /* We only need to use floating point to determine the correct
+ stretch vector for one line's worth. */
+ if (overflow2(sizeof (int), srcW)) {
+ return;
+ }
+ if (overflow2(sizeof (int), srcH)) {
+ return;
+ }
+ stx = (int *) gdMalloc (sizeof (int) * srcW);
+ if (!stx) {
+ return;
+ }
+
+ sty = (int *) gdMalloc (sizeof (int) * srcH);
+ if (!sty) {
+ gdFree(stx);
+ return;
+ }
+
+ /* Fixed by Mao Morimoto 2.0.16 */
+ for (i = 0; (i < srcW); i++) {
+ stx[i] = dstW * (i + 1) / srcW - dstW * i / srcW;
+ }
+ for (i = 0; (i < srcH); i++) {
+ sty[i] = dstH * (i + 1) / srcH - dstH * i / srcH;
+ }
+ for (i = 0; (i < gdMaxColors); i++) {
+ colorMap[i] = (-1);
+ }
+ toy = dstY;
+ for (y = srcY; (y < (srcY + srcH)); y++) {
+ for (ydest = 0; (ydest < sty[y - srcY]); ydest++) {
+ tox = dstX;
+ for (x = srcX; (x < (srcX + srcW)); x++) {
+ int nc = 0;
+ int mapTo;
+ if (!stx[x - srcX]) {
+ continue;
+ }
+ if (dst->trueColor) {
+ /* 2.0.9: Thorben Kundinger: Maybe the source image is not
+ a truecolor image */
+ if (!src->trueColor) {
+ int tmp = gdImageGetPixel (src, x, y);
+ mapTo = gdImageGetTrueColorPixel (src, x, y);
+ if (gdImageGetTransparent (src) == tmp) {
+ /* 2.0.21, TK: not tox++ */
+ tox += stx[x - srcX];
+ continue;
+ }
+ } else {
+ /* TK: old code follows */
+ mapTo = gdImageGetTrueColorPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == mapTo) {
+ /* 2.0.21, TK: not tox++ */
+ tox += stx[x - srcX];
+ continue;
+ }
+ }
+ } else {
+ c = gdImageGetPixel (src, x, y);
+ /* Added 7/24/95: support transparent copies */
+ if (gdImageGetTransparent (src) == c) {
+ tox += stx[x - srcX];
+ continue;
+ }
+ if (src->trueColor) {
+ /* Remap to the palette available in the
+ destination image. This is slow and
+ works badly. */
+ mapTo = gdImageColorResolveAlpha (dst,
+ gdTrueColorGetRed (c),
+ gdTrueColorGetGreen
+ (c),
+ gdTrueColorGetBlue
+ (c),
+ gdTrueColorGetAlpha
+ (c));
+ } else {
+ /* Have we established a mapping for this color? */
+ if (colorMap[c] == (-1)) {
+ /* If it's the same image, mapping is trivial */
+ if (dst == src) {
+ nc = c;
+ } else {
+ /* Find or create the best match */
+ /* 2.0.5: can't use gdTrueColorGetRed, etc with palette */
+ nc = gdImageColorResolveAlpha (dst,
+ gdImageRed (src,
+ c),
+ gdImageGreen
+ (src, c),
+ gdImageBlue (src,
+ c),
+ gdImageAlpha
+ (src, c));
+ }
+ colorMap[c] = nc;
+ }
+ mapTo = colorMap[c];
+ }
+ }
+ for (i = 0; (i < stx[x - srcX]); i++) {
+ gdImageSetPixel (dst, tox, toy, mapTo);
+ tox++;
+ }
+ }
+ toy++;
+ }
+ }
+ gdFree (stx);
+ gdFree (sty);
+}
+
+/**
+ * Function: gdImageCopyRotated
+ *
+ * Copy a rotated area from an image to another image
+ *
+ * The area is counter-clockwise rotated using nearest-neighbor interpolation.
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the center of the area to copy to.
+ * dstY - The y-coordinate of the center of the area to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * srcW - The width of the area to copy from.
+ * srcH - The height of the area to copy from.
+ * angle - The angle in degrees.
+ *
+ * See also:
+ * - <gdImageRotateInterpolated>
+ */
+BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst,
+ gdImagePtr src,
+ double dstX, double dstY,
+ int srcX, int srcY,
+ int srcWidth, int srcHeight, int angle)
+{
+ double dx, dy;
+ double radius = sqrt (srcWidth * srcWidth + srcHeight * srcHeight);
+ double aCos = cos (angle * .0174532925);
+ double aSin = sin (angle * .0174532925);
+ double scX = srcX + ((double) srcWidth) / 2;
+ double scY = srcY + ((double) srcHeight) / 2;
+ int cmap[gdMaxColors];
+ int i;
+
+ /*
+ 2.0.34: transparency preservation. The transparentness of
+ the transparent color is more important than its hue.
+ */
+ if (src->transparent != -1) {
+ if (dst->transparent == -1) {
+ dst->transparent = src->transparent;
+ }
+ }
+
+ for (i = 0; (i < gdMaxColors); i++) {
+ cmap[i] = (-1);
+ }
+ for (dy = dstY - radius; (dy <= dstY + radius); dy++) {
+ for (dx = dstX - radius; (dx <= dstX + radius); dx++) {
+ double sxd = (dx - dstX) * aCos - (dy - dstY) * aSin;
+ double syd = (dy - dstY) * aCos + (dx - dstX) * aSin;
+ int sx = sxd + scX;
+ int sy = syd + scY;
+ if ((sx >= srcX) && (sx < srcX + srcWidth) &&
+ (sy >= srcY) && (sy < srcY + srcHeight)) {
+ int c = gdImageGetPixel (src, sx, sy);
+ /* 2.0.34: transparency wins */
+ if (c == src->transparent) {
+ gdImageSetPixel (dst, dx, dy, dst->transparent);
+ } else if (!src->trueColor) {
+ /* Use a table to avoid an expensive
+ lookup on every single pixel */
+ if (cmap[c] == -1) {
+ cmap[c] = gdImageColorResolveAlpha (dst,
+ gdImageRed (src, c),
+ gdImageGreen (src,
+ c),
+ gdImageBlue (src,
+ c),
+ gdImageAlpha (src,
+ c));
+ }
+ gdImageSetPixel (dst, dx, dy, cmap[c]);
+ } else {
+ gdImageSetPixel (dst,
+ dx, dy,
+ gdImageColorResolveAlpha (dst,
+ gdImageRed (src,
+ c),
+ gdImageGreen
+ (src, c),
+ gdImageBlue (src,
+ c),
+ gdImageAlpha
+ (src, c)));
+ }
+ }
+ }
+ }
+}
+
+/* When gd 1.x was first created, floating point was to be avoided.
+ These days it is often faster than table lookups or integer
+ arithmetic. The routine below is shamelessly, gloriously
+ floating point. TBB */
+
+/* 2.0.10: cast instead of floor() yields 35% performance improvement.
+ Thanks to John Buckman. */
+
+#define floor2(exp) ((long) exp)
+/*#define floor2(exp) floor(exp)*/
+
+/**
+ * Function: gdImageCopyResampled
+ *
+ * Copy a resampled area from an image to another image
+ *
+ * If the source and destination area differ in size, the area will be resized
+ * using bilinear interpolation for truecolor images, and nearest-neighbor
+ * interpolation for palette images.
+ *
+ * Parameters:
+ * dst - The destination image.
+ * src - The source image.
+ * dstX - The x-coordinate of the upper left corner to copy to.
+ * dstY - The y-coordinate of the upper left corner to copy to.
+ * srcX - The x-coordinate of the upper left corner to copy from.
+ * srcY - The y-coordinate of the upper left corner to copy from.
+ * dstW - The width of the area to copy to.
+ * dstH - The height of the area to copy to.
+ * srcW - The width of the area to copy from.
+ * srcH - The height of the area to copy from.
+ *
+ * See also:
+ * - <gdImageCopyResized>
+ * - <gdImageScale>
+ */
+BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst,
+ gdImagePtr src,
+ int dstX, int dstY,
+ int srcX, int srcY,
+ int dstW, int dstH, int srcW, int srcH)
+{
+ int x, y;
+ if (!dst->trueColor) {
+ gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
+ return;
+ }
+ for (y = dstY; (y < dstY + dstH); y++) {
+ for (x = dstX; (x < dstX + dstW); x++) {
+ float sy1, sy2, sx1, sx2;
+ float sx, sy;
+ float spixels = 0.0;
+ float red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
+ float alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0;
+ sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH;
+ sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH;
+ sy = sy1;
+ do {
+ float yportion;
+ if (floorf(sy) == floorf(sy1)) {
+ yportion = 1.0 - (sy - floorf(sy));
+ if (yportion > sy2 - sy1) {
+ yportion = sy2 - sy1;
+ }
+ sy = floorf(sy);
+ } else if (sy == floorf(sy2)) {
+ yportion = sy2 - floorf(sy2);
+ } else {
+ yportion = 1.0;
+ }
+ sx1 = ((float)(x - dstX)) * (float) srcW / dstW;
+ sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW;
+ sx = sx1;
+ do {
+ float xportion;
+ float pcontribution;
+ int p;
+ if (floorf(sx) == floorf(sx1)) {
+ xportion = 1.0 - (sx - floorf(sx));
+ if (xportion > sx2 - sx1) {
+ xportion = sx2 - sx1;
+ }
+ sx = floorf(sx);
+ } else if (sx == floorf(sx2)) {
+ xportion = sx2 - floorf(sx2);
+ } else {
+ xportion = 1.0;
+ }
+ pcontribution = xportion * yportion;
+ p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY);
+
+ alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution;
+ red += gdTrueColorGetRed (p) * alpha_factor;
+ green += gdTrueColorGetGreen (p) * alpha_factor;
+ blue += gdTrueColorGetBlue (p) * alpha_factor;
+ alpha += gdTrueColorGetAlpha (p) * pcontribution;
+ alpha_sum += alpha_factor;
+ contrib_sum += pcontribution;
+ spixels += xportion * yportion;
+ sx += 1.0;
+ }
+ while (sx < sx2);
+ sy += 1.0f;
+ }
+ while (sy < sy2);
+
+ if (spixels != 0.0) {
+ red /= spixels;
+ green /= spixels;
+ blue /= spixels;
+ alpha /= spixels;
+ }
+ if ( alpha_sum != 0.0) {
+ if( contrib_sum != 0.0) {
+ alpha_sum /= contrib_sum;
+ }
+ red /= alpha_sum;
+ green /= alpha_sum;
+ blue /= alpha_sum;
+ }
+ /* Clamping to allow for rounding errors above */
+ if (red > 255.0) {
+ red = 255.0;
+ }
+ if (green > 255.0) {
+ green = 255.0;
+ }
+ if (blue > 255.0f) {
+ blue = 255.0;
+ }
+ if (alpha > gdAlphaMax) {
+ alpha = gdAlphaMax;
+ }
+ gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
+ }
+ }
+}
+
+/**
+ * Group: Polygons
+ */
+
+/**
+ * Function: gdImagePolygon
+ *
+ * Draws a closed polygon
+ *
+ * Parameters:
+ * im - The image.
+ * p - The vertices as array of <gdPoint>s.
+ * n - The number of vertices.
+ * c - The color.
+ *
+ * See also:
+ * - <gdImageOpenPolygon>
+ * - <gdImageFilledPolygon>
+ */
+BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
+{
+ if (n <= 0) {
+ return;
+ }
+
+
+ gdImageLine (im, p->x, p->y, p[n - 1].x, p[n - 1].y, c);
+ gdImageOpenPolygon (im, p, n, c);
+}
+
+/**
+ * Function: gdImageOpenPolygon
+ *
+ * Draws an open polygon
+ *
+ * Parameters:
+ * im - The image.
+ * p - The vertices as array of <gdPoint>s.
+ * n - The number of vertices.
+ * c - The color
+ *
+ * See also:
+ * - <gdImagePolygon>
+ */
+BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
+{
+ int i;
+ int lx, ly;
+ if (n <= 0) {
+ return;
+ }
+
+
+ lx = p->x;
+ ly = p->y;
+ for (i = 1; (i < n); i++) {
+ p++;
+ gdImageLine (im, lx, ly, p->x, p->y, c);
+ lx = p->x;
+ ly = p->y;
+ }
+
+}
+
+/* THANKS to Kirsten Schulz for the polygon fixes! */
+
+/* The intersection finding technique of this code could be improved */
+/* by remembering the previous intertersection, and by using the slope. */
+/* That could help to adjust intersections to produce a nice */
+/* interior_extrema. */
+
+/**
+ * Function: gdImageFilledPolygon
+ *
+ * Draws a filled polygon
+ *
+ * The polygon is filled using the even-odd fillrule what can leave unfilled
+ * regions inside of self-intersecting polygons. This behavior might change in
+ * a future version.
+ *
+ * Parameters:
+ * im - The image.
+ * p - The vertices as array of <gdPoint>s.
+ * n - The number of vertices.
+ * c - The color
+ *
+ * See also:
+ * - <gdImagePolygon>
+ */
+BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
+{
+ int i;
+ int j;
+ int index;
+ int y;
+ int miny, maxy, pmaxy;
+ int x1, y1;
+ int x2, y2;
+ int ind1, ind2;
+ int ints;
+ int fill_color;
+ if (n <= 0) {
+ return;
+ }
+
+ if (c == gdAntiAliased) {
+ fill_color = im->AA_color;
+ } else {
+ fill_color = c;
+ }
+ if (!im->polyAllocated) {
+ if (overflow2(sizeof (int), n)) {
+ return;
+ }
+ im->polyInts = (int *) gdMalloc (sizeof (int) * n);
+ if (!im->polyInts) {
+ return;
+ }
+ im->polyAllocated = n;
+ }
+ if (im->polyAllocated < n) {
+ while (im->polyAllocated < n) {
+ im->polyAllocated *= 2;
+ }
+ if (overflow2(sizeof (int), im->polyAllocated)) {
+ return;
+ }
+ im->polyInts = (int *) gdReallocEx (im->polyInts,
+ sizeof (int) * im->polyAllocated);
+ if (!im->polyInts) {
+ return;
+ }
+ }
+ miny = p[0].y;
+ maxy = p[0].y;
+ for (i = 1; (i < n); i++) {
+ if (p[i].y < miny) {
+ miny = p[i].y;
+ }
+ if (p[i].y > maxy) {
+ maxy = p[i].y;
+ }
+ }
+ /* necessary special case: horizontal line */
+ if (n > 1 && miny == maxy) {
+ x1 = x2 = p[0].x;
+ for (i = 1; (i < n); i++) {
+ if (p[i].x < x1) {
+ x1 = p[i].x;
+ } else if (p[i].x > x2) {
+ x2 = p[i].x;
+ }
+ }
+ gdImageLine(im, x1, miny, x2, miny, c);
+ return;
+ }
+ pmaxy = maxy;
+ /* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
+ /* 2.0.26: clipping rectangle is even better */
+ if (miny < im->cy1) {
+ miny = im->cy1;
+ }
+ if (maxy > im->cy2) {
+ maxy = im->cy2;
+ }
+ /* Fix in 1.3: count a vertex only once */
+ for (y = miny; (y <= maxy); y++) {
+ ints = 0;
+ for (i = 0; (i < n); i++) {
+ if (!i) {
+ ind1 = n - 1;
+ ind2 = 0;
+ } else {
+ ind1 = i - 1;
+ ind2 = i;
+ }
+ y1 = p[ind1].y;
+ y2 = p[ind2].y;
+ if (y1 < y2) {
+ x1 = p[ind1].x;
+ x2 = p[ind2].x;
+ } else if (y1 > y2) {
+ y2 = p[ind1].y;
+ y1 = p[ind2].y;
+ x2 = p[ind1].x;
+ x1 = p[ind2].x;
+ } else {
+ continue;
+ }
+
+ /* Do the following math as float intermediately, and round to ensure
+ * that Polygon and FilledPolygon for the same set of points have the
+ * same footprint. */
+
+ if ((y >= y1) && (y < y2)) {
+ im->polyInts[ints++] = (int) ((float) ((y - y1) * (x2 - x1)) /
+ (float) (y2 - y1) + 0.5 + x1);
+ } else if ((y == pmaxy) && (y == y2)) {
+ im->polyInts[ints++] = x2;
+ }
+ }
+ /*
+ 2.0.26: polygons pretty much always have less than 100 points,
+ and most of the time they have considerably less. For such trivial
+ cases, insertion sort is a good choice. Also a good choice for
+ future implementations that may wish to indirect through a table.
+ */
+ for (i = 1; (i < ints); i++) {
+ index = im->polyInts[i];
+ j = i;
+ while ((j > 0) && (im->polyInts[j - 1] > index)) {
+ im->polyInts[j] = im->polyInts[j - 1];
+ j--;
+ }
+ im->polyInts[j] = index;
+ }
+ for (i = 0; (i < (ints-1)); i += 2) {
+ /* 2.0.29: back to gdImageLine to prevent segfaults when
+ performing a pattern fill */
+ gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
+ fill_color);
+ }
+ }
+ /* If we are drawing this AA, then redraw the border with AA lines. */
+ /* This doesn't work as well as I'd like, but it doesn't clash either. */
+ if (c == gdAntiAliased) {
+ gdImagePolygon (im, p, n, c);
+ }
+}
+
+/**
+ * Group: other
+ */
+
+static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t);
+
+/**
+ * Function: gdImageSetStyle
+ *
+ * Sets the style for following drawing operations
+ *
+ * Parameters:
+ * im - The image.
+ * style - An array of color values.
+ * noOfPixel - The number of color values.
+ */
+BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
+{
+ if (im->style) {
+ gdFree (im->style);
+ }
+ if (overflow2(sizeof (int), noOfPixels)) {
+ return;
+ }
+ im->style = (int *) gdMalloc (sizeof (int) * noOfPixels);
+ if (!im->style) {
+ return;
+ }
+ memcpy (im->style, style, sizeof (int) * noOfPixels);
+ im->styleLength = noOfPixels;
+ im->stylePos = 0;
+}
+
+/**
+ * Function: gdImageSetThickness
+ *
+ * Sets the thickness for following drawing operations
+ *
+ * Parameters:
+ * im - The image.
+ * thickness - The thickness in pixels.
+ */
+BGD_DECLARE(void) gdImageSetThickness (gdImagePtr im, int thickness)
+{
+ im->thick = thickness;
+}
+
+/**
+ * Function: gdImageSetBrush
+ *
+ * Sets the brush for following drawing operations
+ *
+ * Parameters:
+ * im - The image.
+ * brush - The brush image.
+ */
+BGD_DECLARE(void) gdImageSetBrush (gdImagePtr im, gdImagePtr brush)
+{
+ int i;
+ im->brush = brush;
+ if ((!im->trueColor) && (!im->brush->trueColor)) {
+ for (i = 0; (i < gdImageColorsTotal (brush)); i++) {
+ int index;
+ index = gdImageColorResolveAlpha (im,
+ gdImageRed (brush, i),
+ gdImageGreen (brush, i),
+ gdImageBlue (brush, i),
+ gdImageAlpha (brush, i));
+ im->brushColorMap[i] = index;
+ }
+ }
+}
+
+/*
+ Function: gdImageSetTile
+*/
+BGD_DECLARE(void) gdImageSetTile (gdImagePtr im, gdImagePtr tile)
+{
+ int i;
+ im->tile = tile;
+ if ((!im->trueColor) && (!im->tile->trueColor)) {
+ for (i = 0; (i < gdImageColorsTotal (tile)); i++) {
+ int index;
+ index = gdImageColorResolveAlpha (im,
+ gdImageRed (tile, i),
+ gdImageGreen (tile, i),
+ gdImageBlue (tile, i),
+ gdImageAlpha (tile, i));
+ im->tileColorMap[i] = index;
+ }
+ }
+}
+
+/**
+ * Function: gdImageSetAntiAliased
+ *
+ * Set the color for subsequent anti-aliased drawing
+ *
+ * If <gdAntiAliased> is passed as color to drawing operations that support
+ * anti-aliased drawing (such as <gdImageLine> and <gdImagePolygon>), the actual
+ * color to be used can be set with this function.
+ *
+ * Example: draw an anti-aliased blue line:
+ * | gdImageSetAntiAliased(im, gdTrueColorAlpha(0, 0, gdBlueMax, gdAlphaOpaque));
+ * | gdImageLine(im, 10,10, 20,20, gdAntiAliased);
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ *
+ * See also:
+ * - <gdImageSetAntiAliasedDontBlend>
+ */
+BGD_DECLARE(void) gdImageSetAntiAliased (gdImagePtr im, int c)
+{
+ im->AA = 1;
+ im->AA_color = c;
+ im->AA_dont_blend = -1;
+}
+
+/**
+ * Function: gdImageSetAntiAliasedDontBlend
+ *
+ * Set the color and "dont_blend" color for subsequent anti-aliased drawing
+ *
+ * This extended variant of <gdImageSetAntiAliased> allows to also specify a
+ * (background) color that will not be blended in anti-aliased drawing
+ * operations.
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ * dont_blend - Whether to blend.
+ */
+BGD_DECLARE(void) gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend)
+{
+ im->AA = 1;
+ im->AA_color = c;
+ im->AA_dont_blend = dont_blend;
+}
+
+/**
+ * Function: gdImageInterlace
+ *
+ * Sets whether an image is interlaced
+ *
+ * This is relevant only when saving the image in a format that supports
+ * interlacing.
+ *
+ * Parameters:
+ * im - The image.
+ * interlaceArg - Whether the image is interlaced.
+ *
+ * See also:
+ * - <gdImageGetInterlaced>
+*/
+BGD_DECLARE(void) gdImageInterlace (gdImagePtr im, int interlaceArg)
+{
+ im->interlace = interlaceArg;
+}
+
+/**
+ * Function: gdImageCompare
+ *
+ * Compare two images
+ *
+ * Parameters:
+ * im1 - An image.
+ * im2 - Another image.
+ *
+ * Returns:
+ * A bitmask of <Image Comparison> flags where each set flag signals
+ * which attributes of the images are different.
+ */
+BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2)
+{
+ int x, y;
+ int p1, p2;
+ int cmpStatus = 0;
+ int sx, sy;
+
+ if (im1->interlace != im2->interlace) {
+ cmpStatus |= GD_CMP_INTERLACE;
+ }
+
+ if (im1->transparent != im2->transparent) {
+ cmpStatus |= GD_CMP_TRANSPARENT;
+ }
+
+ if (im1->trueColor != im2->trueColor) {
+ cmpStatus |= GD_CMP_TRUECOLOR;
+ }
+
+ sx = im1->sx;
+ if (im1->sx != im2->sx) {
+ cmpStatus |= GD_CMP_SIZE_X + GD_CMP_IMAGE;
+ if (im2->sx < im1->sx) {
+ sx = im2->sx;
+ }
+ }
+
+ sy = im1->sy;
+ if (im1->sy != im2->sy) {
+ cmpStatus |= GD_CMP_SIZE_Y + GD_CMP_IMAGE;
+ if (im2->sy < im1->sy) {
+ sy = im2->sy;
+ }
+ }
+
+ if (im1->colorsTotal != im2->colorsTotal) {
+ cmpStatus |= GD_CMP_NUM_COLORS;
+ }
+
+ for (y = 0; (y < sy); y++) {
+ for (x = 0; (x < sx); x++) {
+ p1 =
+ im1->trueColor ? gdImageTrueColorPixel (im1, x,
+ y) :
+ gdImagePalettePixel (im1, x, y);
+ p2 =
+ im2->trueColor ? gdImageTrueColorPixel (im2, x,
+ y) :
+ gdImagePalettePixel (im2, x, y);
+ if (gdImageRed (im1, p1) != gdImageRed (im2, p2)) {
+ cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
+ break;
+ }
+ if (gdImageGreen (im1, p1) != gdImageGreen (im2, p2)) {
+ cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
+ break;
+ }
+ if (gdImageBlue (im1, p1) != gdImageBlue (im2, p2)) {
+ cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
+ break;
+ }
+#if 0
+ /* Soon we'll add alpha channel to palettes */
+ if (gdImageAlpha (im1, p1) != gdImageAlpha (im2, p2)) {
+ cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
+ break;
+ }
+#endif
+ }
+ if (cmpStatus & GD_CMP_COLOR) {
+ break;
+ };
+ }
+
+ return cmpStatus;
+}
+
+
+/* Thanks to Frank Warmerdam for this superior implementation
+ of gdAlphaBlend(), which merges alpha in the
+ destination color much better. */
+
+/**
+ * Function: gdAlphaBlend
+ *
+ * Blend two colors
+ *
+ * Parameters:
+ * dst - The color to blend onto.
+ * src - The color to blend.
+ *
+ * See also:
+ * - <gdImageAlphaBlending>
+ * - <gdLayerOverlay>
+ * - <gdLayerMultiply>
+ */
+BGD_DECLARE(int) gdAlphaBlend (int dst, int src)
+{
+ int src_alpha = gdTrueColorGetAlpha(src);
+ int dst_alpha, alpha, red, green, blue;
+ int src_weight, dst_weight, tot_weight;
+
+ /* -------------------------------------------------------------------- */
+ /* Simple cases we want to handle fast. */
+ /* -------------------------------------------------------------------- */
+ if( src_alpha == gdAlphaOpaque )
+ return src;
+
+ dst_alpha = gdTrueColorGetAlpha(dst);
+ if( src_alpha == gdAlphaTransparent )
+ return dst;
+ if( dst_alpha == gdAlphaTransparent )
+ return src;
+
+ /* -------------------------------------------------------------------- */
+ /* What will the source and destination alphas be? Note that */
+ /* the destination weighting is substantially reduced as the */
+ /* overlay becomes quite opaque. */
+ /* -------------------------------------------------------------------- */
+ src_weight = gdAlphaTransparent - src_alpha;
+ dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
+ tot_weight = src_weight + dst_weight;
+
+ /* -------------------------------------------------------------------- */
+ /* What red, green and blue result values will we use? */
+ /* -------------------------------------------------------------------- */
+ alpha = src_alpha * dst_alpha / gdAlphaMax;
+
+ red = (gdTrueColorGetRed(src) * src_weight
+ + gdTrueColorGetRed(dst) * dst_weight) / tot_weight;
+ green = (gdTrueColorGetGreen(src) * src_weight
+ + gdTrueColorGetGreen(dst) * dst_weight) / tot_weight;
+ blue = (gdTrueColorGetBlue(src) * src_weight
+ + gdTrueColorGetBlue(dst) * dst_weight) / tot_weight;
+
+ /* -------------------------------------------------------------------- */
+ /* Return merged result. */
+ /* -------------------------------------------------------------------- */
+ return ((alpha << 24) + (red << 16) + (green << 8) + blue);
+}
+
+static int gdAlphaOverlayColor (int src, int dst, int max );
+
+/**
+ * Function: gdLayerOverlay
+ *
+ * Overlay two colors
+ *
+ * Parameters:
+ * dst - The color to overlay onto.
+ * src - The color to overlay.
+ *
+ * See also:
+ * - <gdImageAlphaBlending>
+ * - <gdAlphaBlend>
+ * - <gdLayerMultiply>
+ */
+BGD_DECLARE(int) gdLayerOverlay (int dst, int src)
+{
+ int a1, a2;
+ a1 = gdAlphaMax - gdTrueColorGetAlpha(dst);
+ a2 = gdAlphaMax - gdTrueColorGetAlpha(src);
+ return ( ((gdAlphaMax - a1*a2/gdAlphaMax) << 24) +
+ (gdAlphaOverlayColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), gdRedMax ) << 16) +
+ (gdAlphaOverlayColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), gdGreenMax ) << 8) +
+ (gdAlphaOverlayColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), gdBlueMax ))
+ );
+}
+
+/* Apply 'overlay' effect - background pixels are colourised by the foreground colour */
+static int gdAlphaOverlayColor (int src, int dst, int max )
+{
+ dst = dst << 1;
+ if( dst > max ) {
+ /* in the "light" zone */
+ return dst + (src << 1) - (dst * src / max) - max;
+ } else {
+ /* in the "dark" zone */
+ return dst * src / max;
+ }
+}
+
+/**
+ * Function: gdLayerMultiply
+ *
+ * Overlay two colors with multiply effect
+ *
+ * Parameters:
+ * dst - The color to overlay onto.
+ * src - The color to overlay.
+ *
+ * See also:
+ * - <gdImageAlphaBlending>
+ * - <gdAlphaBlend>
+ * - <gdLayerOverlay>
+ */
+BGD_DECLARE(int) gdLayerMultiply (int dst, int src)
+{
+ int a1, a2, r1, r2, g1, g2, b1, b2;
+ a1 = gdAlphaMax - gdTrueColorGetAlpha(src);
+ a2 = gdAlphaMax - gdTrueColorGetAlpha(dst);
+
+ r1 = gdRedMax - (a1 * (gdRedMax - gdTrueColorGetRed(src))) / gdAlphaMax;
+ r2 = gdRedMax - (a2 * (gdRedMax - gdTrueColorGetRed(dst))) / gdAlphaMax;
+ g1 = gdGreenMax - (a1 * (gdGreenMax - gdTrueColorGetGreen(src))) / gdAlphaMax;
+ g2 = gdGreenMax - (a2 * (gdGreenMax - gdTrueColorGetGreen(dst))) / gdAlphaMax;
+ b1 = gdBlueMax - (a1 * (gdBlueMax - gdTrueColorGetBlue(src))) / gdAlphaMax;
+ b2 = gdBlueMax - (a2 * (gdBlueMax - gdTrueColorGetBlue(dst))) / gdAlphaMax ;
+
+ a1 = gdAlphaMax - a1;
+ a2 = gdAlphaMax - a2;
+ return ( ((a1*a2/gdAlphaMax) << 24) +
+ ((r1*r2/gdRedMax) << 16) +
+ ((g1*g2/gdGreenMax) << 8) +
+ ((b1*b2/gdBlueMax))
+ );
+}
+
+/**
+ * Function: gdImageAlphaBlending
+ *
+ * Set the effect for subsequent drawing operations
+ *
+ * Note that the effect is used for truecolor images only.
+ *
+ * Parameters:
+ * im - The image.
+ * alphaBlendingArg - The effect.
+ *
+ * See also:
+ * - <Effects>
+ */
+BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
+{
+ im->alphaBlendingFlag = alphaBlendingArg;
+}
+
+/**
+ * Function: gdImageSaveAlpha
+ *
+ * Sets the save alpha flag
+ *
+ * The save alpha flag specifies whether the alpha channel of the pixels should
+ * be saved. This is supported only for image formats that support full alpha
+ * transparency, e.g. PNG.
+ */
+BGD_DECLARE(void) gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg)
+{
+ im->saveAlphaFlag = saveAlphaArg;
+}
+
+/**
+ * Function: gdImageSetClip
+ *
+ * Sets the clipping rectangle
+ *
+ * The clipping rectangle restricts the drawing area for following drawing
+ * operations.
+ *
+ * Parameters:
+ * im - The image.
+ * x1 - The x-coordinate of the upper left corner.
+ * y1 - The y-coordinate of the upper left corner.
+ * x2 - The x-coordinate of the lower right corner.
+ * y2 - The y-coordinate of the lower right corner.
+ *
+ * See also:
+ * - <gdImageGetClip>
+ */
+BGD_DECLARE(void) gdImageSetClip (gdImagePtr im, int x1, int y1, int x2, int y2)
+{
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ if (x1 >= im->sx) {
+ x1 = im->sx - 1;
+ }
+ if (x2 < 0) {
+ x2 = 0;
+ }
+ if (x2 >= im->sx) {
+ x2 = im->sx - 1;
+ }
+ if (y1 < 0) {
+ y1 = 0;
+ }
+ if (y1 >= im->sy) {
+ y1 = im->sy - 1;
+ }
+ if (y2 < 0) {
+ y2 = 0;
+ }
+ if (y2 >= im->sy) {
+ y2 = im->sy - 1;
+ }
+ im->cx1 = x1;
+ im->cy1 = y1;
+ im->cx2 = x2;
+ im->cy2 = y2;
+}
+
+/**
+ * Function: gdImageGetClip
+ *
+ * Gets the current clipping rectangle
+ *
+ * Parameters:
+ * im - The image.
+ * x1P - (out) The x-coordinate of the upper left corner.
+ * y1P - (out) The y-coordinate of the upper left corner.
+ * x2P - (out) The x-coordinate of the lower right corner.
+ * y2P - (out) The y-coordinate of the lower right corner.
+ *
+ * See also:
+ * - <gdImageSetClip>
+ */
+BGD_DECLARE(void) gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
+{
+ *x1P = im->cx1;
+ *y1P = im->cy1;
+ *x2P = im->cx2;
+ *y2P = im->cy2;
+}
+
+/**
+ * Function: gdImageSetResolution
+ *
+ * Sets the resolution of an image.
+ *
+ * Parameters:
+ * im - The image.
+ * res_x - The horizontal resolution in DPI.
+ * res_y - The vertical resolution in DPI.
+ *
+ * See also:
+ * - <gdImageResolutionX>
+ * - <gdImageResolutionY>
+ */
+BGD_DECLARE(void) gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y)
+{
+ if (res_x > 0) im->res_x = res_x;
+ if (res_y > 0) im->res_y = res_y;
+}
+
+/*
+ * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org)
+ * */
+#define BLEND_COLOR(a, nc, c, cc) \
+nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
+
+static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
+{
+ int dr,dg,db,p,r,g,b;
+
+ /* 2.0.34: watch out for out of range calls */
+ if (!gdImageBoundsSafeMacro(im, x, y)) {
+ return;
+ }
+ p = gdImageGetPixel(im,x,y);
+ /* TBB: we have to implement the dont_blend stuff to provide
+ the full feature set of the old implementation */
+ if ((p == color)
+ || ((p == im->AA_dont_blend)
+ && (t != 0x00))) {
+ return;
+ }
+ dr = gdTrueColorGetRed(color);
+ dg = gdTrueColorGetGreen(color);
+ db = gdTrueColorGetBlue(color);
+
+ r = gdTrueColorGetRed(p);
+ g = gdTrueColorGetGreen(p);
+ b = gdTrueColorGetBlue(p);
+
+ BLEND_COLOR(t, dr, r, dr);
+ BLEND_COLOR(t, dg, g, dg);
+ BLEND_COLOR(t, db, b, db);
+ im->tpixels[y][x] = gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque);
+}
+
+static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
+{
+ /* keep them as 32bits */
+ long x, y, inc, frac;
+ long dx, dy,tmp;
+ int w, wid, wstart;
+ int thick = im->thick;
+
+ if (!im->trueColor) {
+ /* TBB: don't crash when the image is of the wrong type */
+ gdImageLine(im, x1, y1, x2, y2, col);
+ return;
+ }
+
+ /* TBB: use the clipping rectangle */
+ if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
+ return;
+ if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
+ return;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ if (dx == 0 && dy == 0) {
+ /* TBB: allow setting points */
+ gdImageSetAAPixelColor(im, x1, y1, col, 0xFF);
+ return;
+ } else {
+ double ag;
+ /* Cast the long to an int to avoid compiler warnings about truncation.
+ * This isn't a problem as computed dy/dx values came from ints above. */
+ ag = fabs(abs((int)dy) < abs((int)dx) ? cos(atan2(dy, dx)) : sin(atan2(dy, dx)));
+ if (ag != 0) {
+ wid = thick / ag;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0) {
+ wid = 1;
+ }
+ }
+
+ /* Axis aligned lines */
+ if (dx == 0) {
+ gdImageVLine(im, x1, y1, y2, col);
+ return;
+ } else if (dy == 0) {
+ gdImageHLine(im, y1, x1, x2, col);
+ return;
+ }
+
+ if (abs((int)dx) > abs((int)dy)) {
+ if (dx < 0) {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ dx = x2 - x1;
+ dy = y2 - y1;
+ }
+ y = y1;
+ inc = (dy * 65536) / dx;
+ frac = 0;
+ /* TBB: set the last pixel for consistency (<=) */
+ for (x = x1 ; x <= x2 ; x++) {
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetAAPixelColor(im, x , w , col , (frac >> 8) & 0xFF);
+ gdImageSetAAPixelColor(im, x , w + 1 , col, (~frac >> 8) & 0xFF);
+ }
+ frac += inc;
+ if (frac >= 65536) {
+ frac -= 65536;
+ y++;
+ } else if (frac < 0) {
+ frac += 65536;
+ y--;
+ }
+ }
+ } else {
+ if (dy < 0) {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ dx = x2 - x1;
+ dy = y2 - y1;
+ }
+ x = x1;
+ inc = (dx * 65536) / dy;
+ frac = 0;
+ /* TBB: set the last pixel for consistency (<=) */
+ for (y = y1 ; y <= y2 ; y++) {
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++) {
+ gdImageSetAAPixelColor(im, w , y , col, (frac >> 8) & 0xFF);
+ gdImageSetAAPixelColor(im, w + 1, y, col, (~frac >> 8) & 0xFF);
+ }
+ frac += inc;
+ if (frac >= 65536) {
+ frac -= 65536;
+ x++;
+ } else if (frac < 0) {
+ frac += 65536;
+ x--;
+ }
+ }
+ }
+}
+
+
+/**
+ * Function: gdImagePaletteToTrueColor
+ *
+ * Convert a palette image to true color
+ *
+ * Parameters:
+ * src - The image.
+ *
+ * Returns:
+ * Non-zero if the conversion succeeded, zero otherwise.
+ *
+ * See also:
+ * - <gdImageTrueColorToPalette>
+ */
+BGD_DECLARE(int) gdImagePaletteToTrueColor(gdImagePtr src)
+{
+ unsigned int y;
+ unsigned int yy;
+
+ if (src == NULL) {
+ return 0;
+ }
+
+ if (src->trueColor == 1) {
+ return 1;
+ } else {
+ unsigned int x;
+ const unsigned int sy = gdImageSY(src);
+ const unsigned int sx = gdImageSX(src);
+
+ src->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
+ if (src->tpixels == NULL) {
+ return 0;
+ }
+
+ for (y = 0; y < sy; y++) {
+ const unsigned char *src_row = src->pixels[y];
+ int * dst_row;
+
+ /* no need to calloc it, we overwrite all pxl anyway */
+ src->tpixels[y] = (int *) gdMalloc(sx * sizeof(int));
+ if (src->tpixels[y] == NULL) {
+ goto clean_on_error;
+ }
+
+ dst_row = src->tpixels[y];
+ for (x = 0; x < sx; x++) {
+ const unsigned char c = *(src_row + x);
+ if (c == src->transparent) {
+ *(dst_row + x) = gdTrueColorAlpha(0, 0, 0, 127);
+ } else {
+ *(dst_row + x) = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
+ }
+ }
+ }
+ }
+
+ /* free old palette buffer (y is sy) */
+ for (yy = 0; yy < y; yy++) {
+ gdFree(src->pixels[yy]);
+ }
+ gdFree(src->pixels);
+ src->trueColor = 1;
+ src->pixels = NULL;
+ src->alphaBlendingFlag = 0;
+ src->saveAlphaFlag = 1;
+
+ if (src->transparent >= 0) {
+ const unsigned char c = src->transparent;
+ src->transparent = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
+ }
+
+ return 1;
+
+clean_on_error:
+ /* free new true color buffer (y is not allocated, have failed) */
+ for (yy = 0; yy < y; yy++) {
+ gdFree(src->tpixels[yy]);
+ }
+ gdFree(src->tpixels);
+ return 0;
+}
diff --git a/libmscgen/gd.h b/libmscgen/gd.h
new file mode 100644
index 0000000..d6bbebd
--- /dev/null
+++ b/libmscgen/gd.h
@@ -0,0 +1,1620 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+#ifndef GD_H
+#define GD_H 1
+
+/* Version information. This gets parsed by build scripts as well as
+ * gcc so each #define line in this group must also be splittable on
+ * whitespace, take the form GD_*_VERSION and contain the magical
+ * trailing comment. */
+#define GD_MAJOR_VERSION 2 /*version605b5d1778*/
+#define GD_MINOR_VERSION 2 /*version605b5d1778*/
+#define GD_RELEASE_VERSION 4 /*version605b5d1778*/
+#define GD_EXTRA_VERSION "" /*version605b5d1778*/
+/* End parsable section. */
+
+/* The version string. This is constructed from the version number
+ * parts above via macro abuse^Wtrickery. */
+#define GDXXX_VERSION_STR(mjr, mnr, rev, ext) mjr "." mnr "." rev ext
+#define GDXXX_STR(s) GDXXX_SSTR(s) /* Two levels needed to expand args. */
+#define GDXXX_SSTR(s) #s
+
+#define GD_VERSION_STRING \
+ GDXXX_VERSION_STR(GDXXX_STR(GD_MAJOR_VERSION), \
+ GDXXX_STR(GD_MINOR_VERSION), \
+ GDXXX_STR(GD_RELEASE_VERSION), \
+ GD_EXTRA_VERSION)
+
+
+/* Do the DLL dance: dllexport when building the DLL,
+ dllimport when importing from it, nothing when
+ not on Silly Silly Windows (tm Aardman Productions). */
+
+/* 2.0.20: for headers */
+
+/* 2.0.24: __stdcall also needed for Visual BASIC
+ and other languages. This breaks ABI compatibility
+ with previous DLL revs, but it's necessary. */
+
+/* 2.0.29: WIN32 programmers can declare the NONDLL macro if they
+ wish to build gd as a static library or by directly including
+ the gd sources in a project. */
+
+/* http://gcc.gnu.org/wiki/Visibility */
+
+#define BGD_EXPORT_DATA_PROT
+#define BGD_DECLARE(rt) rt
+
+/* VS2012+ disable keyword macroizing unless _ALLOW_KEYWORD_MACROS is set
+ We define inline, snprintf, and strcasecmp if they're missing
+*/
+#ifdef _MSC_VER
+# define _ALLOW_KEYWORD_MACROS
+# ifndef inline
+# define inline __inline
+# endif
+# ifndef strcasecmp
+# define strcasecmp _stricmp
+# endif
+#if _MSC_VER < 1900
+ extern int snprintf(char*, size_t, const char*, ...);
+#endif
+#endif
+
+#ifdef __cplusplus
+ extern "C"
+ {
+#endif
+
+/* gd.h: declarations file for the graphic-draw module.
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "AS IS." Thomas Boutell and
+ * Boutell.Com, Inc. disclaim all warranties, either express or implied,
+ * including but not limited to implied warranties of merchantability and
+ * fitness for a particular purpose, with respect to this code and accompanying
+ * documentation. */
+
+/* stdio is needed for file I/O. */
+#include <stdio.h>
+#include <stdarg.h>
+//#include "gd_io.h"
+
+/* The maximum number of palette entries in palette-based images.
+ In the wonderful new world of gd 2.0, you can of course have
+ many more colors when using truecolor mode. */
+
+#define gdMaxColors 256
+
+/* Image type. See functions below; you will not need to change
+ the elements directly. Use the provided macros to
+ access sx, sy, the color table, and colorsTotal for
+ read-only purposes. */
+
+/* If 'truecolor' is set true, the image is truecolor;
+ pixels are represented by integers, which
+ must be 32 bits wide or more.
+
+ True colors are repsented as follows:
+
+ ARGB
+
+ Where 'A' (alpha channel) occupies only the
+ LOWER 7 BITS of the MSB. This very small
+ loss of alpha channel resolution allows gd 2.x
+ to keep backwards compatibility by allowing
+ signed integers to be used to represent colors,
+ and negative numbers to represent special cases,
+ just as in gd 1.x. */
+
+#define gdAlphaMax 127
+#define gdAlphaOpaque 0
+#define gdAlphaTransparent 127
+#define gdRedMax 255
+#define gdGreenMax 255
+#define gdBlueMax 255
+
+/**
+ * Group: Color Decomposition
+ */
+
+/**
+ * Macro: gdTrueColorGetAlpha
+ *
+ * Gets the alpha channel value
+ *
+ * Parameters:
+ * c - The color
+ *
+ * See also:
+ * - <gdTrueColorAlpha>
+ */
+#define gdTrueColorGetAlpha(c) (((c) & 0x7F000000) >> 24)
+
+/**
+ * Macro: gdTrueColorGetRed
+ *
+ * Gets the red channel value
+ *
+ * Parameters:
+ * c - The color
+ *
+ * See also:
+ * - <gdTrueColorAlpha>
+ */
+#define gdTrueColorGetRed(c) (((c) & 0xFF0000) >> 16)
+
+/**
+ * Macro: gdTrueColorGetGreen
+ *
+ * Gets the green channel value
+ *
+ * Parameters:
+ * c - The color
+ *
+ * See also:
+ * - <gdTrueColorAlpha>
+ */
+#define gdTrueColorGetGreen(c) (((c) & 0x00FF00) >> 8)
+
+/**
+ * Macro: gdTrueColorGetBlue
+ *
+ * Gets the blue channel value
+ *
+ * Parameters:
+ * c - The color
+ *
+ * See also:
+ * - <gdTrueColorAlpha>
+ */
+#define gdTrueColorGetBlue(c) ((c) & 0x0000FF)
+
+/**
+ * Group: Effects
+ *
+ * The layering effect
+ *
+ * When pixels are drawn the new colors are "mixed" with the background
+ * depending on the effect.
+ *
+ * Note that the effect does not apply to palette images, where pixels
+ * are always replaced.
+ *
+ * Modes:
+ * gdEffectReplace - replace pixels
+ * gdEffectAlphaBlend - blend pixels, see <gdAlphaBlend>
+ * gdEffectNormal - default mode; same as gdEffectAlphaBlend
+ * gdEffectOverlay - overlay pixels, see <gdLayerOverlay>
+ * gdEffectMultiply - overlay pixels with multiply effect, see
+ * <gdLayerMultiply>
+ *
+ * See also:
+ * - <gdImageAlphaBlending>
+ */
+#define gdEffectReplace 0
+#define gdEffectAlphaBlend 1
+#define gdEffectNormal 2
+#define gdEffectOverlay 3
+#define gdEffectMultiply 4
+
+#define GD_TRUE 1
+#define GD_FALSE 0
+
+#define GD_EPSILON 1e-6
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+/* This function accepts truecolor pixel values only. The
+ source color is composited with the destination color
+ based on the alpha channel value of the source color.
+ The resulting color is opaque. */
+
+BGD_DECLARE(int) gdAlphaBlend (int dest, int src);
+BGD_DECLARE(int) gdLayerOverlay (int dest, int src);
+BGD_DECLARE(int) gdLayerMultiply (int dest, int src);
+
+
+/**
+ * Group: Color Quantization
+ *
+ * Enum: gdPaletteQuantizationMethod
+ *
+ * Constants:
+ * GD_QUANT_DEFAULT - GD_QUANT_LIQ if libimagequant is available,
+ * GD_QUANT_JQUANT otherwise.
+ * GD_QUANT_JQUANT - libjpeg's old median cut. Fast, but only uses 16-bit
+ * color.
+ * GD_QUANT_NEUQUANT - NeuQuant - approximation using Kohonen neural network.
+ * GD_QUANT_LIQ - A combination of algorithms used in libimagequant
+ * aiming for the highest quality at cost of speed.
+ *
+ * Note that GD_QUANT_JQUANT does not retain the alpha channel, and
+ * GD_QUANT_NEUQUANT does not support dithering.
+ *
+ * See also:
+ * - <gdImageTrueColorToPaletteSetMethod>
+ */
+enum gdPaletteQuantizationMethod {
+ GD_QUANT_DEFAULT = 0,
+ GD_QUANT_JQUANT = 1,
+ GD_QUANT_NEUQUANT = 2,
+ GD_QUANT_LIQ = 3
+};
+
+
+/**
+ * Group: Transform
+ *
+ * Constants: gdInterpolationMethod
+ *
+ * GD_BELL - Bell
+ * GD_BESSEL - Bessel
+ * GD_BILINEAR_FIXED - fixed point bilinear
+ * GD_BICUBIC - Bicubic
+ * GD_BICUBIC_FIXED - fixed point bicubic integer
+ * GD_BLACKMAN - Blackman
+ * GD_BOX - Box
+ * GD_BSPLINE - BSpline
+ * GD_CATMULLROM - Catmullrom
+ * GD_GAUSSIAN - Gaussian
+ * GD_GENERALIZED_CUBIC - Generalized cubic
+ * GD_HERMITE - Hermite
+ * GD_HAMMING - Hamming
+ * GD_HANNING - Hannig
+ * GD_MITCHELL - Mitchell
+ * GD_NEAREST_NEIGHBOUR - Nearest neighbour interpolation
+ * GD_POWER - Power
+ * GD_QUADRATIC - Quadratic
+ * GD_SINC - Sinc
+ * GD_TRIANGLE - Triangle
+ * GD_WEIGHTED4 - 4 pixels weighted bilinear interpolation
+ * GD_LINEAR - bilinear interpolation
+ *
+ * See also:
+ * - <gdImageSetInterpolationMethod>
+ * - <gdImageGetInterpolationMethod>
+ */
+typedef enum {
+ GD_DEFAULT = 0,
+ GD_BELL,
+ GD_BESSEL,
+ GD_BILINEAR_FIXED,
+ GD_BICUBIC,
+ GD_BICUBIC_FIXED,
+ GD_BLACKMAN,
+ GD_BOX,
+ GD_BSPLINE,
+ GD_CATMULLROM,
+ GD_GAUSSIAN,
+ GD_GENERALIZED_CUBIC,
+ GD_HERMITE,
+ GD_HAMMING,
+ GD_HANNING,
+ GD_MITCHELL,
+ GD_NEAREST_NEIGHBOUR,
+ GD_POWER,
+ GD_QUADRATIC,
+ GD_SINC,
+ GD_TRIANGLE,
+ GD_WEIGHTED4,
+ GD_LINEAR,
+ GD_METHOD_COUNT = 23
+} gdInterpolationMethod;
+
+/* define struct with name and func ptr and add it to gdImageStruct gdInterpolationMethod interpolation; */
+
+/* Interpolation function ptr */
+typedef double (* interpolation_method )(double);
+
+
+/*
+ Group: Types
+
+ typedef: gdImage
+
+ typedef: gdImagePtr
+
+ The data structure in which gd stores images. <gdImageCreate>,
+ <gdImageCreateTrueColor> and the various image file-loading functions
+ return a pointer to this type, and the other functions expect to
+ receive a pointer to this type as their first argument.
+
+ *gdImagePtr* is a pointer to *gdImage*.
+
+ See also:
+ <Accessor Macros>
+
+ (Previous versions of this library encouraged directly manipulating
+ the contents ofthe struct but we are attempting to move away from
+ this practice so the fields are no longer documented here. If you
+ need to poke at the internals of this struct, feel free to look at
+ *gd.h*.)
+*/
+typedef struct gdImageStruct {
+ /* Palette-based image pixels */
+ unsigned char **pixels;
+ int sx;
+ int sy;
+ /* These are valid in palette images only. See also
+ 'alpha', which appears later in the structure to
+ preserve binary backwards compatibility */
+ int colorsTotal;
+ int red[gdMaxColors];
+ int green[gdMaxColors];
+ int blue[gdMaxColors];
+ int open[gdMaxColors];
+ /* For backwards compatibility, this is set to the
+ first palette entry with 100% transparency,
+ and is also set and reset by the
+ gdImageColorTransparent function. Newer
+ applications can allocate palette entries
+ with any desired level of transparency; however,
+ bear in mind that many viewers, notably
+ many web browsers, fail to implement
+ full alpha channel for PNG and provide
+ support for full opacity or transparency only. */
+ int transparent;
+ int *polyInts;
+ int polyAllocated;
+ struct gdImageStruct *brush;
+ struct gdImageStruct *tile;
+ int brushColorMap[gdMaxColors];
+ int tileColorMap[gdMaxColors];
+ int styleLength;
+ int stylePos;
+ int *style;
+ int interlace;
+ /* New in 2.0: thickness of line. Initialized to 1. */
+ int thick;
+ /* New in 2.0: alpha channel for palettes. Note that only
+ Macintosh Internet Explorer and (possibly) Netscape 6
+ really support multiple levels of transparency in
+ palettes, to my knowledge, as of 2/15/01. Most
+ common browsers will display 100% opaque and
+ 100% transparent correctly, and do something
+ unpredictable and/or undesirable for levels
+ in between. TBB */
+ int alpha[gdMaxColors];
+ /* Truecolor flag and pixels. New 2.0 fields appear here at the
+ end to minimize breakage of existing object code. */
+ int trueColor;
+ int **tpixels;
+ /* Should alpha channel be copied, or applied, each time a
+ pixel is drawn? This applies to truecolor images only.
+ No attempt is made to alpha-blend in palette images,
+ even if semitransparent palette entries exist.
+ To do that, build your image as a truecolor image,
+ then quantize down to 8 bits. */
+ int alphaBlendingFlag;
+ /* Should the alpha channel of the image be saved? This affects
+ PNG at the moment; other future formats may also
+ have that capability. JPEG doesn't. */
+ int saveAlphaFlag;
+
+ /* There should NEVER BE ACCESSOR MACROS FOR ITEMS BELOW HERE, so this
+ part of the structure can be safely changed in new releases. */
+
+ /* 2.0.12: anti-aliased globals. 2.0.26: just a few vestiges after
+ switching to the fast, memory-cheap implementation from PHP-gd. */
+ int AA;
+ int AA_color;
+ int AA_dont_blend;
+
+ /* 2.0.12: simple clipping rectangle. These values
+ must be checked for safety when set; please use
+ gdImageSetClip */
+ int cx1;
+ int cy1;
+ int cx2;
+ int cy2;
+
+ /* 2.1.0: allows to specify resolution in dpi */
+ unsigned int res_x;
+ unsigned int res_y;
+
+ /* Selects quantization method, see gdImageTrueColorToPaletteSetMethod() and gdPaletteQuantizationMethod enum. */
+ int paletteQuantizationMethod;
+ /* speed/quality trade-off. 1 = best quality, 10 = best speed. 0 = method-specific default.
+ Applicable to GD_QUANT_LIQ and GD_QUANT_NEUQUANT. */
+ int paletteQuantizationSpeed;
+ /* Image will remain true-color if conversion to palette cannot achieve given quality.
+ Value from 1 to 100, 1 = ugly, 100 = perfect. Applicable to GD_QUANT_LIQ.*/
+ int paletteQuantizationMinQuality;
+ /* Image will use minimum number of palette colors needed to achieve given quality. Must be higher than paletteQuantizationMinQuality
+ Value from 1 to 100, 1 = ugly, 100 = perfect. Applicable to GD_QUANT_LIQ.*/
+ int paletteQuantizationMaxQuality;
+ gdInterpolationMethod interpolation_id;
+ interpolation_method interpolation;
+}
+gdImage;
+
+typedef gdImage *gdImagePtr;
+
+
+/* Point type for use in polygon drawing. */
+
+/**
+ * Group: Types
+ *
+ * typedef: gdPointF
+ * Defines a point in a 2D coordinate system using floating point
+ * values.
+ * x - Floating point position (increase from left to right)
+ * y - Floating point Row position (increase from top to bottom)
+ *
+ * typedef: gdPointFPtr
+ * Pointer to a <gdPointF>
+ *
+ * See also:
+ * <gdImageCreate>, <gdImageCreateTrueColor>,
+ **/
+typedef struct
+{
+ double x, y;
+}
+gdPointF, *gdPointFPtr;
+
+
+/*
+ Group: Types
+
+ typedef: gdFont
+
+ typedef: gdFontPtr
+
+ A font structure, containing the bitmaps of all characters in a
+ font. Used to declare the characteristics of a font. Text-output
+ functions expect these as their second argument, following the
+ <gdImagePtr> argument. <gdFontGetSmall> and <gdFontGetLarge> both
+ return one.
+
+ You can provide your own font data by providing such a structure and
+ the associated pixel array. You can determine the width and height
+ of a single character in a font by examining the w and h members of
+ the structure. If you will not be creating your own fonts, you will
+ not need to concern yourself with the rest of the components of this
+ structure.
+
+ Please see the files gdfontl.c and gdfontl.h for an example of
+ the proper declaration of this structure.
+
+ > typedef struct {
+ > // # of characters in font
+ > int nchars;
+ > // First character is numbered... (usually 32 = space)
+ > int offset;
+ > // Character width and height
+ > int w;
+ > int h;
+ > // Font data; array of characters, one row after another.
+ > // Easily included in code, also easily loaded from
+ > // data files.
+ > char *data;
+ > } gdFont;
+
+ gdFontPtr is a pointer to gdFont.
+
+*/
+typedef struct {
+ /* # of characters in font */
+ int nchars;
+ /* First character is numbered... (usually 32 = space) */
+ int offset;
+ /* Character width and height */
+ int w;
+ int h;
+ /* Font data; array of characters, one row after another.
+ Easily included in code, also easily loaded from
+ data files. */
+ char *data;
+}
+gdFont;
+
+/* Text functions take these. */
+typedef gdFont *gdFontPtr;
+
+typedef void(*gdErrorMethod)(int, const char *, va_list);
+
+BGD_DECLARE(void) gdSetErrorMethod(gdErrorMethod);
+BGD_DECLARE(void) gdClearErrorMethod(void);
+
+/* For backwards compatibility only. Use gdImageSetStyle()
+ for MUCH more flexible line drawing. Also see
+ gdImageSetBrush(). */
+#define gdDashSize 4
+
+/**
+ * Group: Colors
+ *
+ * Colors are always of type int which is supposed to be at least 32 bit large.
+ *
+ * Kinds of colors:
+ * true colors - ARGB values where the alpha channel is stored as most
+ * significant, and the blue channel as least significant
+ * byte. Note that the alpha channel only uses the 7 least
+ * significant bits.
+ * Don't rely on the internal representation, though, and
+ * use <gdTrueColorAlpha> to compose a truecolor value, and
+ * <gdTrueColorGetAlpha>, <gdTrueColorGetRed>,
+ * <gdTrueColorGetGreen> and <gdTrueColorGetBlue> to access
+ * the respective channels.
+ * palette indexes - The index of a color palette entry (0-255).
+ * special colors - As listed in the following section.
+ *
+ * Constants: Special Colors
+ * gdStyled - use the current style, see <gdImageSetStyle>
+ * gdBrushed - use the current brush, see <gdImageSetBrush>
+ * gdStyledBrushed - use the current style and brush
+ * gdTiled - use the current tile, see <gdImageSetTile>
+ * gdTransparent - indicate transparency, what is not the same as the
+ * transparent color index; used for lines only
+ * gdAntiAliased - draw anti aliased
+ */
+
+#define gdStyled (-2)
+#define gdBrushed (-3)
+#define gdStyledBrushed (-4)
+#define gdTiled (-5)
+#define gdTransparent (-6)
+#define gdAntiAliased (-7)
+
+/* Functions to manipulate images. */
+
+/* Creates a palette-based image (up to 256 colors). */
+BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy);
+
+/* An alternate name for the above (2.0). */
+#define gdImageCreatePalette gdImageCreate
+
+/* Creates a truecolor image (millions of colors). */
+BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy);
+
+/* Creates an image from various file types. These functions
+ return a palette or truecolor image based on the
+ nature of the file being loaded. Truecolor PNG
+ stays truecolor; palette PNG stays palette-based;
+ JPEG is always truecolor. */
+BGD_DECLARE(gdImagePtr) gdImageCreateFromPng (FILE * fd);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromPngCtx (gdIOCtxPtr in);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromPngPtr (int size, void *data);
+
+/* These read the first frame only */
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGif (FILE * fd);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx (gdIOCtxPtr in);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGifPtr (int size, void *data);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMP (FILE * inFile);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMPCtx (gdIOCtx * infile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromWBMPPtr (int size, void *data);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromJpeg (FILE * infile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegEx (FILE * infile, int ignore_warning);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtx (gdIOCtx * infile);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtxEx (gdIOCtx * infile, int ignore_warning);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtr (int size, void *data);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtrEx (int size, void *data, int ignore_warning);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromTiff(FILE *inFile);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffCtx(gdIOCtx *infile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromTiffPtr(int size, void *data);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromTga( FILE * fp );
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromTgaCtx(gdIOCtx* ctx);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromTgaPtr(int size, void *data);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromBmp (FILE * inFile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromBmpPtr (int size, void *data);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromBmpCtx (gdIOCtxPtr infile);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromFile(const char *filename);
+
+
+/*
+ Group: Types
+
+ typedef: gdSource
+
+ typedef: gdSourcePtr
+
+ *Note:* This interface is *obsolete* and kept only for
+ *compatibility. Use <gdIOCtx> instead.
+
+ Represents a source from which a PNG can be read. Programmers who
+ do not wish to read PNGs from a file can provide their own
+ alternate input mechanism, using the <gdImageCreateFromPngSource>
+ function. See the documentation of that function for an example of
+ the proper use of this type.
+
+ > typedef struct {
+ > int (*source) (void *context, char *buffer, int len);
+ > void *context;
+ > } gdSource, *gdSourcePtr;
+
+ The source function must return -1 on error, otherwise the number
+ of bytes fetched. 0 is EOF, not an error!
+
+ 'context' will be passed to your source function.
+
+*/
+typedef struct {
+ int (*source) (void *context, char *buffer, int len);
+ void *context;
+}
+gdSource, *gdSourcePtr;
+
+/* Deprecated in favor of gdImageCreateFromPngCtx */
+BGD_DECLARE(gdImagePtr) gdImageCreateFromPngSource (gdSourcePtr in);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGd (FILE * in);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromGdCtx (gdIOCtxPtr in);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGdPtr (int size, void *data);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2 (FILE * in);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ptr (int size, void *data);
+
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Part (FILE * in, int srcx, int srcy, int w,
+ int h);
+//BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtxPtr in, int srcx, int srcy,
+// int w, int h);
+BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy,
+ int w, int h);
+/* 2.0.10: prototype was missing */
+BGD_DECLARE(gdImagePtr) gdImageCreateFromXbm (FILE * in);
+//BGD_DECLARE(void) gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out);
+
+/* NOTE: filename, not FILE */
+BGD_DECLARE(gdImagePtr) gdImageCreateFromXpm (char *filename);
+
+BGD_DECLARE(void) gdImageDestroy (gdImagePtr im);
+
+/* Replaces or blends with the background depending on the
+ most recent call to gdImageAlphaBlending and the
+ alpha channel value of 'color'; default is to overwrite.
+ Tiling and line styling are also implemented
+ here. All other gd drawing functions pass through this call,
+ allowing for many useful effects.
+ Overlay and multiply effects are used when gdImageAlphaBlending
+ is passed gdEffectOverlay and gdEffectMultiply */
+
+BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color);
+/* FreeType 2 text output with hook to extra flags */
+
+BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y);
+BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
+
+BGD_DECLARE(void) gdImageAABlend (gdImagePtr im);
+
+BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color);
+
+/* For backwards compatibility only. Use gdImageSetStyle()
+ for much more flexible line drawing. */
+BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color);
+/* Corners specified (not width and height). Upper left first, lower right
+ second. */
+BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color);
+/* Solid bar. Upper left corner first, lower right corner second. */
+BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
+ int color);
+BGD_DECLARE(void) gdImageSetClip(gdImagePtr im, int x1, int y1, int x2, int y2);
+BGD_DECLARE(void) gdImageGetClip(gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P);
+BGD_DECLARE(void) gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y);
+BGD_DECLARE(int) gdImageBoundsSafe (gdImagePtr im, int x, int y);
+BGD_DECLARE(void) gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c,
+ int color);
+BGD_DECLARE(void) gdImageCharUp (gdImagePtr im, gdFontPtr f, int x, int y, int c,
+ int color);
+BGD_DECLARE(void) gdImageString (gdImagePtr im, gdFontPtr f, int x, int y,
+ unsigned char *s, int color);
+BGD_DECLARE(void) gdImageStringUp (gdImagePtr im, gdFontPtr f, int x, int y,
+ unsigned char *s, int color);
+BGD_DECLARE(void) gdImageString16 (gdImagePtr im, gdFontPtr f, int x, int y,
+ unsigned short *s, int color);
+BGD_DECLARE(void) gdImageStringUp16 (gdImagePtr im, gdFontPtr f, int x, int y,
+ unsigned short *s, int color);
+
+/* 2.0.16: for thread-safe use of gdImageStringFT and friends,
+ call this before allowing any thread to call gdImageStringFT.
+ Otherwise it is invoked by the first thread to invoke
+ gdImageStringFT, with a very small but real risk of a race condition.
+ Return 0 on success, nonzero on failure to initialize freetype. */
+BGD_DECLARE(int) gdFontCacheSetup (void);
+
+/* Optional: clean up after application is done using fonts in
+ gdImageStringFT(). */
+BGD_DECLARE(void) gdFontCacheShutdown (void);
+/* 2.0.20: for backwards compatibility. A few applications did start calling
+ this function when it first appeared although it was never documented.
+ Simply invokes gdFontCacheShutdown. */
+BGD_DECLARE(void) gdFreeFontCache (void);
+
+/* Calls gdImageStringFT. Provided for backwards compatibility only. */
+BGD_DECLARE(char *) gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist,
+ double ptsize, double angle, int x, int y,
+ char *string);
+
+/* FreeType 2 text output */
+BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
+ double ptsize, double angle, int x, int y,
+ char *string);
+
+
+/*
+ Group: Types
+
+ typedef: gdFTStringExtra
+
+ typedef: gdFTStringExtraPtr
+
+ A structure and associated pointer type used to pass additional
+ parameters to the <gdImageStringFTEx> function. See
+ <gdImageStringFTEx> for the structure definition.
+
+ Thanks to Wez Furlong.
+*/
+
+/* 2.0.5: provides an extensible way to pass additional parameters.
+ Thanks to Wez Furlong, sorry for the delay. */
+typedef struct {
+ int flags; /* Logical OR of gdFTEX_ values */
+ double linespacing; /* fine tune line spacing for '\n' */
+ int charmap; /* TBB: 2.0.12: may be gdFTEX_Unicode,
+ gdFTEX_Shift_JIS, gdFTEX_Big5,
+ or gdFTEX_Adobe_Custom;
+ when not specified, maps are searched
+ for in the above order. */
+ int hdpi; /* if (flags & gdFTEX_RESOLUTION) */
+ int vdpi; /* if (flags & gdFTEX_RESOLUTION) */
+ char *xshow; /* if (flags & gdFTEX_XSHOW)
+ then, on return, xshow is a malloc'ed
+ string containing xshow position data for
+ the last string.
+
+ NB. The caller is responsible for gdFree'ing
+ the xshow string.
+ */
+ char *fontpath; /* if (flags & gdFTEX_RETURNFONTPATHNAME)
+ then, on return, fontpath is a malloc'ed
+ string containing the actual font file path name
+ used, which can be interesting when fontconfig
+ is in use.
+
+ The caller is responsible for gdFree'ing the
+ fontpath string.
+ */
+
+}
+gdFTStringExtra, *gdFTStringExtraPtr;
+
+#define gdFTEX_LINESPACE 1
+#define gdFTEX_CHARMAP 2
+#define gdFTEX_RESOLUTION 4
+#define gdFTEX_DISABLE_KERNING 8
+#define gdFTEX_XSHOW 16
+/* The default unless gdFTUseFontConfig(1); has been called:
+ fontlist is a full or partial font file pathname or list thereof
+ (i.e. just like before 2.0.29) */
+#define gdFTEX_FONTPATHNAME 32
+/* Necessary to use fontconfig patterns instead of font pathnames
+ as the fontlist argument, unless gdFTUseFontConfig(1); has
+ been called. New in 2.0.29 */
+#define gdFTEX_FONTCONFIG 64
+/* Sometimes interesting when fontconfig is used: the fontpath
+ element of the structure above will contain a gdMalloc'd string
+ copy of the actual font file pathname used, if this flag is set
+ when the call is made */
+#define gdFTEX_RETURNFONTPATHNAME 128
+
+/* If flag is nonzero, the fontlist parameter to gdImageStringFT
+ and gdImageStringFTEx shall be assumed to be a fontconfig font pattern
+ if fontconfig was compiled into gd. This function returns zero
+ if fontconfig is not available, nonzero otherwise. */
+BGD_DECLARE(int) gdFTUseFontConfig(int flag);
+
+/* These are NOT flags; set one in 'charmap' if you set the
+ gdFTEX_CHARMAP bit in 'flags'. */
+#define gdFTEX_Unicode 0
+#define gdFTEX_Shift_JIS 1
+#define gdFTEX_Big5 2
+#define gdFTEX_Adobe_Custom 3
+
+BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
+ double ptsize, double angle, int x, int y,
+ char *string, gdFTStringExtraPtr strex);
+
+
+/*
+ Group: Types
+
+ typedef: gdPoint
+
+ typedef: gdPointPtr
+
+ Represents a point in the coordinate space of the image; used by
+ <gdImagePolygon>, <gdImageOpenPolygon> and <gdImageFilledPolygon>
+ for polygon drawing.
+
+ > typedef struct {
+ > int x, y;
+ > } gdPoint, *gdPointPtr;
+
+*/
+typedef struct {
+ int x, y;
+}
+gdPoint, *gdPointPtr;
+
+/**
+ * Typedef: gdRect
+ *
+ * A rectangle in the coordinate space of the image
+ *
+ * Members:
+ * x - The x-coordinate of the upper left corner.
+ * y - The y-coordinate of the upper left corner.
+ * width - The width.
+ * height - The height.
+ *
+ * Typedef: gdRectPtr
+ *
+ * A pointer to a <gdRect>
+ */
+typedef struct {
+ int x, y;
+ int width, height;
+}
+gdRect, *gdRectPtr;
+
+
+BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c);
+BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
+BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c);
+
+/* These functions still work with truecolor images,
+ for which they never return error. */
+BGD_DECLARE(int) gdImageColorAllocate (gdImagePtr im, int r, int g, int b);
+/* gd 2.0: palette entries with non-opaque transparency are permitted. */
+BGD_DECLARE(int) gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a);
+/* Assumes opaque is the preferred alpha channel value */
+BGD_DECLARE(int) gdImageColorClosest (gdImagePtr im, int r, int g, int b);
+/* Closest match taking all four parameters into account.
+ A slightly different color with the same transparency
+ beats the exact same color with radically different
+ transparency */
+BGD_DECLARE(int) gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a);
+/* An alternate method */
+BGD_DECLARE(int) gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b);
+/* Returns exact, 100% opaque matches only */
+BGD_DECLARE(int) gdImageColorExact (gdImagePtr im, int r, int g, int b);
+/* Returns an exact match only, including alpha */
+BGD_DECLARE(int) gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a);
+/* Opaque only */
+BGD_DECLARE(int) gdImageColorResolve (gdImagePtr im, int r, int g, int b);
+/* Based on gdImageColorExactAlpha and gdImageColorClosestAlpha */
+BGD_DECLARE(int) gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a);
+
+/* A simpler way to obtain an opaque truecolor value for drawing on a
+ truecolor image. Not for use with palette images! */
+
+#define gdTrueColor(r, g, b) (((r) << 16) + \
+ ((g) << 8) + \
+ (b))
+
+/**
+ * Group: Color Composition
+ *
+ * Macro: gdTrueColorAlpha
+ *
+ * Compose a truecolor value from its components
+ *
+ * Parameters:
+ * r - The red channel (0-255)
+ * g - The green channel (0-255)
+ * b - The blue channel (0-255)
+ * a - The alpha channel (0-127, where 127 is fully transparent, and 0 is
+ * completely opaque).
+ *
+ * See also:
+ * - <gdTrueColorGetAlpha>
+ * - <gdTrueColorGetRed>
+ * - <gdTrueColorGetGreen>
+ * - <gdTrueColorGetBlue>
+ * - <gdImageColorExactAlpha>
+ */
+#define gdTrueColorAlpha(r, g, b, a) (((a) << 24) + \
+ ((r) << 16) + \
+ ((g) << 8) + \
+ (b))
+
+BGD_DECLARE(void) gdImageColorDeallocate (gdImagePtr im, int color);
+
+/* Converts a truecolor image to a palette-based image,
+ using a high-quality two-pass quantization routine
+ which attempts to preserve alpha channel information
+ as well as R/G/B color information when creating
+ a palette. If ditherFlag is set, the image will be
+ dithered to approximate colors better, at the expense
+ of some obvious "speckling." colorsWanted can be
+ anything up to 256. If the original source image
+ includes photographic information or anything that
+ came out of a JPEG, 256 is strongly recommended.
+
+ Better yet, don't use these function -- write real
+ truecolor PNGs and JPEGs. The disk space gain of
+ conversion to palette is not great (for small images
+ it can be negative) and the quality loss is ugly.
+
+ DIFFERENCES: gdImageCreatePaletteFromTrueColor creates and
+ returns a new image. gdImageTrueColorToPalette modifies
+ an existing image, and the truecolor pixels are discarded.
+
+ gdImageTrueColorToPalette() returns TRUE on success, FALSE on failure.
+*/
+
+BGD_DECLARE(gdImagePtr) gdImageCreatePaletteFromTrueColor (gdImagePtr im, int ditherFlag,
+ int colorsWanted);
+
+BGD_DECLARE(int) gdImageTrueColorToPalette (gdImagePtr im, int ditherFlag,
+ int colorsWanted);
+
+BGD_DECLARE(int) gdImagePaletteToTrueColor(gdImagePtr src);
+
+/* An attempt at getting the results of gdImageTrueColorToPalette to
+ * look a bit more like the original (im1 is the original and im2 is
+ * the palette version */
+
+BGD_DECLARE(int) gdImageColorMatch(gdImagePtr im1, gdImagePtr im2);
+
+/* Selects quantization method used for subsequent gdImageTrueColorToPalette calls.
+ See gdPaletteQuantizationMethod enum (e.g. GD_QUANT_NEUQUANT, GD_QUANT_LIQ).
+ Speed is from 1 (highest quality) to 10 (fastest).
+ Speed 0 selects method-specific default (recommended).
+
+ Returns FALSE if the given method is invalid or not available.
+*/
+BGD_DECLARE(int) gdImageTrueColorToPaletteSetMethod (gdImagePtr im, int method, int speed);
+
+/*
+ Chooses quality range that subsequent call to gdImageTrueColorToPalette will aim for.
+ Min and max quality is in range 1-100 (1 = ugly, 100 = perfect). Max must be higher than min.
+ If palette cannot represent image with at least min_quality, then image will remain true-color.
+ If palette can represent image with quality better than max_quality, then lower number of colors will be used.
+ This function has effect only when GD_QUANT_LIQ method has been selected and the source image is true-color.
+*/
+BGD_DECLARE(void) gdImageTrueColorToPaletteSetQuality (gdImagePtr im, int min_quality, int max_quality);
+
+/* Specifies a color index (if a palette image) or an
+ RGB color (if a truecolor image) which should be
+ considered 100% transparent. FOR TRUECOLOR IMAGES,
+ THIS IS IGNORED IF AN ALPHA CHANNEL IS BEING
+ SAVED. Use gdImageSaveAlpha(im, 0); to
+ turn off the saving of a full alpha channel in
+ a truecolor image. Note that gdImageColorTransparent
+ is usually compatible with older browsers that
+ do not understand full alpha channels well. TBB */
+BGD_DECLARE(void) gdImageColorTransparent (gdImagePtr im, int color);
+
+BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr dst, gdImagePtr src);
+
+typedef int (*gdCallbackImageColor)(gdImagePtr im, int src);
+
+BGD_DECLARE(int) gdImageColorReplace(gdImagePtr im, int src, int dst);
+BGD_DECLARE(int) gdImageColorReplaceThreshold(gdImagePtr im, int src, int dst, float threshold);
+BGD_DECLARE(int) gdImageColorReplaceArray(gdImagePtr im, int len, int *src, int *dst);
+BGD_DECLARE(int) gdImageColorReplaceCallback(gdImagePtr im, gdCallbackImageColor callback);
+
+BGD_DECLARE(void) gdImageGif (gdImagePtr im, FILE * out);
+BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * out);
+//BGD_DECLARE(void) gdImagePngCtx (gdImagePtr im, gdIOCtx * out);
+//BGD_DECLARE(void) gdImageGifCtx (gdImagePtr im, gdIOCtx * out);
+BGD_DECLARE(void) gdImageTiff(gdImagePtr im, FILE *outFile);
+BGD_DECLARE(void *) gdImageTiffPtr(gdImagePtr im, int *size);
+//BGD_DECLARE(void) gdImageTiffCtx(gdImagePtr image, gdIOCtx *out);
+
+BGD_DECLARE(void *) gdImageBmpPtr(gdImagePtr im, int *size, int compression);
+BGD_DECLARE(void) gdImageBmp(gdImagePtr im, FILE *outFile, int compression);
+//BGD_DECLARE(void) gdImageBmpCtx(gdImagePtr im, gdIOCtxPtr out, int compression);
+
+/* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
+ 1 is FASTEST but produces larger files, 9 provides the best
+ compression (smallest files) but takes a long time to compress, and
+ -1 selects the default compiled into the zlib library. */
+BGD_DECLARE(void) gdImagePngEx (gdImagePtr im, FILE * out, int level);
+//BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * out, int level);
+
+BGD_DECLARE(void) gdImageWBMP (gdImagePtr image, int fg, FILE * out);
+//BGD_DECLARE(void) gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out);
+
+BGD_DECLARE(int) gdImageFile(gdImagePtr im, const char *filename);
+BGD_DECLARE(int) gdSupportsFileType(const char *filename, int writing);
+
+
+/* Guaranteed to correctly free memory returned by the gdImage*Ptr
+ functions */
+BGD_DECLARE(void) gdFree (void *m);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImageWBMPPtr (gdImagePtr im, int *size, int fg);
+
+/* 100 is highest quality (there is always a little loss with JPEG).
+ 0 is lowest. 10 is about the lowest useful setting. */
+BGD_DECLARE(void) gdImageJpeg (gdImagePtr im, FILE * out, int quality);
+//BGD_DECLARE(void) gdImageJpegCtx (gdImagePtr im, gdIOCtx * out, int quality);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImageJpegPtr (gdImagePtr im, int *size, int quality);
+
+BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization);
+BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile);
+BGD_DECLARE(void *) gdImageWebpPtr (gdImagePtr im, int *size);
+BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization);
+//BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization);
+
+
+/**
+ * Group: GifAnim
+ *
+ * Legal values for Disposal. gdDisposalNone is always used by
+ * the built-in optimizer if previm is passed.
+ *
+ * Constants: gdImageGifAnim
+ *
+ * gdDisposalUnknown - Not recommended
+ * gdDisposalNone - Preserve previous frame
+ * gdDisposalRestoreBackground - First allocated color of palette
+ * gdDisposalRestorePrevious - Restore to before start of frame
+ *
+ * See also:
+ * - <gdImageGifAnimAdd>
+ */
+enum {
+ gdDisposalUnknown,
+ gdDisposalNone,
+ gdDisposalRestoreBackground,
+ gdDisposalRestorePrevious
+};
+
+BGD_DECLARE(void) gdImageGifAnimBegin(gdImagePtr im, FILE *outFile, int GlobalCM, int Loops);
+BGD_DECLARE(void) gdImageGifAnimAdd(gdImagePtr im, FILE *outFile, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
+BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile);
+//BGD_DECLARE(void) gdImageGifAnimBeginCtx(gdImagePtr im, gdIOCtx *out, int GlobalCM, int Loops);
+//BGD_DECLARE(void) gdImageGifAnimAddCtx(gdImagePtr im, gdIOCtx *out, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
+//BGD_DECLARE(void) gdImageGifAnimEndCtx(gdIOCtx *out);
+BGD_DECLARE(void *) gdImageGifAnimBeginPtr(gdImagePtr im, int *size, int GlobalCM, int Loops);
+BGD_DECLARE(void *) gdImageGifAnimAddPtr(gdImagePtr im, int *size, int LocalCM, int LeftOfs, int TopOfs, int Delay, int Disposal, gdImagePtr previm);
+BGD_DECLARE(void *) gdImageGifAnimEndPtr(int *size);
+
+
+
+/*
+ Group: Types
+
+ typedef: gdSink
+
+ typedef: gdSinkPtr
+
+ *Note:* This interface is *obsolete* and kept only for
+ *compatibility*. Use <gdIOCtx> instead.
+
+ Represents a "sink" (destination) to which a PNG can be
+ written. Programmers who do not wish to write PNGs to a file can
+ provide their own alternate output mechanism, using the
+ <gdImagePngToSink> function. See the documentation of that
+ function for an example of the proper use of this type.
+
+ > typedef struct {
+ > int (*sink) (void *context, char *buffer, int len);
+ > void *context;
+ > } gdSink, *gdSinkPtr;
+
+ The _sink_ function must return -1 on error, otherwise the number of
+ bytes written, which must be equal to len.
+
+ _context_ will be passed to your sink function.
+
+*/
+
+typedef struct {
+ int (*sink) (void *context, const char *buffer, int len);
+ void *context;
+}
+gdSink, *gdSinkPtr;
+
+BGD_DECLARE(void) gdImagePngToSink (gdImagePtr im, gdSinkPtr out);
+
+BGD_DECLARE(void) gdImageGd (gdImagePtr im, FILE * out);
+BGD_DECLARE(void) gdImageGd2 (gdImagePtr im, FILE * out, int cs, int fmt);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImageGifPtr (gdImagePtr im, int *size);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImagePngPtr (gdImagePtr im, int *size);
+BGD_DECLARE(void *) gdImagePngPtrEx (gdImagePtr im, int *size, int level);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImageGdPtr (gdImagePtr im, int *size);
+
+/* Best to free this memory with gdFree(), not free() */
+BGD_DECLARE(void *) gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size);
+
+/* Style is a bitwise OR ( | operator ) of these.
+ gdArc and gdChord are mutually exclusive;
+ gdChord just connects the starting and ending
+ angles with a straight line, while gdArc produces
+ a rounded edge. gdPie is a synonym for gdArc.
+ gdNoFill indicates that the arc or chord should be
+ outlined, not filled. gdEdged, used together with
+ gdNoFill, indicates that the beginning and ending
+ angles should be connected to the center; this is
+ a good way to outline (rather than fill) a
+ 'pie slice'. */
+#define gdArc 0
+#define gdPie gdArc
+#define gdChord 1
+#define gdNoFill 2
+#define gdEdged 4
+
+BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s,
+ int e, int color, int style);
+BGD_DECLARE(void) gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
+ int color);
+BGD_DECLARE(void) gdImageEllipse(gdImagePtr im, int cx, int cy, int w, int h, int color);
+BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h,
+ int color);
+BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border,
+ int color);
+BGD_DECLARE(void) gdImageFill (gdImagePtr im, int x, int y, int color);
+BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int w, int h);
+BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int w, int h, int pct);
+BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX,
+ int dstY, int srcX, int srcY, int w, int h,
+ int pct);
+
+/* Stretches or shrinks to fit, as needed. Does NOT attempt
+ to average the entire set of source pixels that scale down onto the
+ destination pixel. */
+BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
+ int srcX, int srcY, int dstW, int dstH, int srcW,
+ int srcH);
+
+/* gd 2.0: stretches or shrinks to fit, as needed. When called with a
+ truecolor destination image, this function averages the
+ entire set of source pixels that scale down onto the
+ destination pixel, taking into account what portion of the
+ destination pixel each source pixel represents. This is a
+ floating point operation, but this is not a performance issue
+ on modern hardware, except for some embedded devices. If the
+ destination is a palette image, gdImageCopyResized is
+ substituted automatically. */
+BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX,
+ int dstY, int srcX, int srcY, int dstW, int dstH,
+ int srcW, int srcH);
+
+/* gd 2.0.8: gdImageCopyRotated is added. Source
+ is a rectangle, with its upper left corner at
+ srcX and srcY. Destination is the *center* of
+ the rotated copy. Angle is in degrees, same as
+ gdImageArc. Floating point destination center
+ coordinates allow accurate rotation of
+ objects of odd-numbered width or height. */
+BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst,
+ gdImagePtr src,
+ double dstX, double dstY,
+ int srcX, int srcY,
+ int srcWidth, int srcHeight, int angle);
+
+BGD_DECLARE(gdImagePtr) gdImageClone (gdImagePtr src);
+
+BGD_DECLARE(void) gdImageSetBrush (gdImagePtr im, gdImagePtr brush);
+BGD_DECLARE(void) gdImageSetTile (gdImagePtr im, gdImagePtr tile);
+BGD_DECLARE(void) gdImageSetAntiAliased (gdImagePtr im, int c);
+BGD_DECLARE(void) gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend);
+BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels);
+/* Line thickness (defaults to 1). Affects lines, ellipses,
+ rectangles, polygons and so forth. */
+BGD_DECLARE(void) gdImageSetThickness (gdImagePtr im, int thickness);
+/* On or off (1 or 0) for all three of these. */
+BGD_DECLARE(void) gdImageInterlace (gdImagePtr im, int interlaceArg);
+BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg);
+BGD_DECLARE(void) gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg);
+
+BGD_DECLARE(gdImagePtr) gdImageNeuQuant(gdImagePtr im, const int max_color, int sample_factor);
+
+enum gdPixelateMode {
+ GD_PIXELATE_UPPERLEFT,
+ GD_PIXELATE_AVERAGE
+};
+
+BGD_DECLARE(int) gdImagePixelate(gdImagePtr im, int block_size, const unsigned int mode);
+
+typedef struct {
+ int sub;
+ int plus;
+ unsigned int num_colors;
+ int *colors;
+ unsigned int seed;
+} gdScatter, *gdScatterPtr;
+
+BGD_DECLARE(int) gdImageScatter(gdImagePtr im, int sub, int plus);
+BGD_DECLARE(int) gdImageScatterColor(gdImagePtr im, int sub, int plus, int colors[], unsigned int num_colors);
+BGD_DECLARE(int) gdImageScatterEx(gdImagePtr im, gdScatterPtr s);
+BGD_DECLARE(int) gdImageSmooth(gdImagePtr im, float weight);
+BGD_DECLARE(int) gdImageMeanRemoval(gdImagePtr im);
+BGD_DECLARE(int) gdImageEmboss(gdImagePtr im);
+BGD_DECLARE(int) gdImageGaussianBlur(gdImagePtr im);
+BGD_DECLARE(int) gdImageEdgeDetectQuick(gdImagePtr src);
+BGD_DECLARE(int) gdImageSelectiveBlur( gdImagePtr src);
+BGD_DECLARE(int) gdImageConvolution(gdImagePtr src, float filter[3][3], float filter_div, float offset);
+BGD_DECLARE(int) gdImageColor(gdImagePtr src, const int red, const int green, const int blue, const int alpha);
+BGD_DECLARE(int) gdImageContrast(gdImagePtr src, double contrast);
+BGD_DECLARE(int) gdImageBrightness(gdImagePtr src, int brightness);
+BGD_DECLARE(int) gdImageGrayScale(gdImagePtr src);
+BGD_DECLARE(int) gdImageNegate(gdImagePtr src);
+
+BGD_DECLARE(gdImagePtr) gdImageCopyGaussianBlurred(gdImagePtr src, int radius,
+ double sigma);
+
+
+/**
+ * Group: Accessor Macros
+ */
+
+/**
+ * Macro: gdImageTrueColor
+ *
+ * Whether an image is a truecolor image.
+ *
+ * Parameters:
+ * im - The image.
+ *
+ * Returns:
+ * Non-zero if the image is a truecolor image, zero for palette images.
+ */
+#define gdImageTrueColor(im) ((im)->trueColor)
+
+/**
+ * Macro: gdImageSX
+ *
+ * Gets the width (in pixels) of an image.
+ *
+ * Parameters:
+ * im - The image.
+ */
+#define gdImageSX(im) ((im)->sx)
+
+/**
+ * Macro: gdImageSY
+ *
+ * Gets the height (in pixels) of an image.
+ *
+ * Parameters:
+ * im - The image.
+ */
+#define gdImageSY(im) ((im)->sy)
+
+/**
+ * Macro: gdImageColorsTotal
+ *
+ * Gets the number of colors in the palette.
+ *
+ * This macro is only valid for palette images.
+ *
+ * Parameters:
+ * im - The image
+ */
+#define gdImageColorsTotal(im) ((im)->colorsTotal)
+
+/**
+ * Macro: gdImageRed
+ *
+ * Gets the red component value of a given color.
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ */
+#define gdImageRed(im, c) ((im)->trueColor ? gdTrueColorGetRed(c) : \
+ (im)->red[(c)])
+
+/**
+ * Macro: gdImageGreen
+ *
+ * Gets the green component value of a given color.
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ */
+#define gdImageGreen(im, c) ((im)->trueColor ? gdTrueColorGetGreen(c) : \
+ (im)->green[(c)])
+
+/**
+ * Macro: gdImageBlue
+ *
+ * Gets the blue component value of a given color.
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ */
+#define gdImageBlue(im, c) ((im)->trueColor ? gdTrueColorGetBlue(c) : \
+ (im)->blue[(c)])
+
+/**
+ * Macro: gdImageAlpha
+ *
+ * Gets the alpha component value of a given color.
+ *
+ * Parameters:
+ * im - The image.
+ * c - The color.
+ */
+#define gdImageAlpha(im, c) ((im)->trueColor ? gdTrueColorGetAlpha(c) : \
+ (im)->alpha[(c)])
+
+/**
+ * Macro: gdImageGetTransparent
+ *
+ * Gets the transparent color of the image.
+ *
+ * Parameters:
+ * im - The image.
+ *
+ * See also:
+ * - <gdImageColorTransparent>
+ */
+#define gdImageGetTransparent(im) ((im)->transparent)
+
+/**
+ * Macro: gdImageGetInterlaced
+ *
+ * Whether an image is interlaced.
+ *
+ * Parameters:
+ * im - The image.
+ *
+ * Returns:
+ * Non-zero for interlaced images, zero otherwise.
+ *
+ * See also:
+ * - <gdImageInterlace>
+ */
+#define gdImageGetInterlaced(im) ((im)->interlace)
+
+/**
+ * Macro: gdImagePalettePixel
+ *
+ * Gets the color of a pixel.
+ *
+ * Calling this macro is only valid for palette images.
+ * No bounds checking is done for the coordinates.
+ *
+ * Parameters:
+ * im - The image.
+ * x - The x-coordinate.
+ * y - The y-coordinate.
+ *
+ * See also:
+ * - <gdImageTrueColorPixel>
+ * - <gdImageGetPixel>
+ */
+#define gdImagePalettePixel(im, x, y) (im)->pixels[(y)][(x)]
+
+/**
+ * Macro: gdImageTrueColorPixel
+ *
+ * Gets the color of a pixel.
+ *
+ * Calling this macro is only valid for truecolor images.
+ * No bounds checking is done for the coordinates.
+ *
+ * Parameters:
+ * im - The image.
+ * x - The x-coordinate.
+ * y - The y-coordinate.
+ *
+ * See also:
+ * - <gdImagePalettePixel>
+ * - <gdImageGetTrueColorPixel>
+ */
+#define gdImageTrueColorPixel(im, x, y) (im)->tpixels[(y)][(x)]
+
+/**
+ * Macro: gdImageResolutionX
+ *
+ * Gets the horizontal resolution in DPI.
+ *
+ * Parameters:
+ * im - The image.
+ *
+ * See also:
+ * - <gdImageResolutionY>
+ * - <gdImageSetResolution>
+ */
+#define gdImageResolutionX(im) (im)->res_x
+
+/**
+ * Macro: gdImageResolutionY
+ *
+ * Gets the vertical resolution in DPI.
+ *
+ * Parameters:
+ * im - The image.
+ *
+ * See also:
+ * - <gdImageResolutionX>
+ * - <gdImageSetResolution>
+ */
+#define gdImageResolutionY(im) (im)->res_y
+
+/* I/O Support routines. */
+
+//BGD_DECLARE(gdIOCtx *) gdNewFileCtx (FILE *);
+/* If data is null, size is ignored and an initial data buffer is
+ allocated automatically. NOTE: this function assumes gd has the right
+ to free or reallocate "data" at will! Also note that gd will free
+ "data" when the IO context is freed. If data is not null, it must point
+ to memory allocated with gdMalloc, or by a call to gdImage[something]Ptr.
+ If not, see gdNewDynamicCtxEx for an alternative. */
+//BGD_DECLARE(gdIOCtx *) gdNewDynamicCtx (int size, void *data);
+/* 2.0.21: if freeFlag is nonzero, gd will free and/or reallocate "data" as
+ needed as described above. If freeFlag is zero, gd will never free
+ or reallocate "data", which means that the context should only be used
+ for *reading* an image from a memory buffer, or writing an image to a
+ memory buffer which is already large enough. If the memory buffer is
+ not large enough and an image write is attempted, the write operation
+ will fail. Those wishing to write an image to a buffer in memory have
+ a much simpler alternative in the gdImage[something]Ptr functions. */
+//BGD_DECLARE(gdIOCtx *) gdNewDynamicCtxEx (int size, void *data, int freeFlag);
+//BGD_DECLARE(gdIOCtx *) gdNewSSCtx (gdSourcePtr in, gdSinkPtr out);
+//BGD_DECLARE(void *) gdDPExtractData (struct gdIOCtx *ctx, int *size);
+
+#define GD2_CHUNKSIZE 128
+#define GD2_CHUNKSIZE_MIN 64
+#define GD2_CHUNKSIZE_MAX 4096
+
+#define GD2_VERS 2
+#define GD2_ID "gd2"
+
+#define GD2_FMT_RAW 1
+#define GD2_FMT_COMPRESSED 2
+
+/* Image comparison definitions */
+BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2);
+
+BGD_DECLARE(void) gdImageFlipHorizontal(gdImagePtr im);
+BGD_DECLARE(void) gdImageFlipVertical(gdImagePtr im);
+BGD_DECLARE(void) gdImageFlipBoth(gdImagePtr im);
+
+#define GD_FLIP_HORINZONTAL 1
+#define GD_FLIP_VERTICAL 2
+#define GD_FLIP_BOTH 3
+
+/**
+ * Group: Crop
+ *
+ * Constants: gdCropMode
+ * GD_CROP_DEFAULT - Default crop mode (4 corners or background)
+ * GD_CROP_TRANSPARENT - Crop using the transparent color
+ * GD_CROP_BLACK - Crop black borders
+ * GD_CROP_WHITE - Crop white borders
+ * GD_CROP_SIDES - Crop using colors of the 4 corners
+ *
+ * See also:
+ * - <gdImageCropAuto>
+ **/
+enum gdCropMode {
+ GD_CROP_DEFAULT = 0,
+ GD_CROP_TRANSPARENT,
+ GD_CROP_BLACK,
+ GD_CROP_WHITE,
+ GD_CROP_SIDES,
+ GD_CROP_THRESHOLD
+};
+
+BGD_DECLARE(gdImagePtr) gdImageCrop(gdImagePtr src, const gdRect *crop);
+BGD_DECLARE(gdImagePtr) gdImageCropAuto(gdImagePtr im, const unsigned int mode);
+BGD_DECLARE(gdImagePtr) gdImageCropThreshold(gdImagePtr im, const unsigned int color, const float threshold);
+
+BGD_DECLARE(int) gdImageSetInterpolationMethod(gdImagePtr im, gdInterpolationMethod id);
+BGD_DECLARE(gdInterpolationMethod) gdImageGetInterpolationMethod(gdImagePtr im);
+
+BGD_DECLARE(gdImagePtr) gdImageScale(const gdImagePtr src, const unsigned int new_width, const unsigned int new_height);
+
+BGD_DECLARE(gdImagePtr) gdImageRotateInterpolated(const gdImagePtr src, const float angle, int bgcolor);
+
+typedef enum {
+ GD_AFFINE_TRANSLATE = 0,
+ GD_AFFINE_SCALE,
+ GD_AFFINE_ROTATE,
+ GD_AFFINE_SHEAR_HORIZONTAL,
+ GD_AFFINE_SHEAR_VERTICAL
+} gdAffineStandardMatrix;
+
+BGD_DECLARE(int) gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src, const double affine[6]);
+BGD_DECLARE(int) gdAffineInvert (double dst[6], const double src[6]);
+BGD_DECLARE(int) gdAffineFlip (double dst_affine[6], const double src_affine[6], const int flip_h, const int flip_v);
+BGD_DECLARE(int) gdAffineConcat (double dst[6], const double m1[6], const double m2[6]);
+
+BGD_DECLARE(int) gdAffineIdentity (double dst[6]);
+BGD_DECLARE(int) gdAffineScale (double dst[6], const double scale_x, const double scale_y);
+BGD_DECLARE(int) gdAffineRotate (double dst[6], const double angle);
+BGD_DECLARE(int) gdAffineShearHorizontal (double dst[6], const double angle);
+BGD_DECLARE(int) gdAffineShearVertical(double dst[6], const double angle);
+BGD_DECLARE(int) gdAffineTranslate (double dst[6], const double offset_x, const double offset_y);
+BGD_DECLARE(double) gdAffineExpansion (const double src[6]);
+BGD_DECLARE(int) gdAffineRectilinear (const double src[6]);
+BGD_DECLARE(int) gdAffineEqual (const double matrix1[6], const double matrix2[6]);
+BGD_DECLARE(int) gdTransformAffineGetImage(gdImagePtr *dst, const gdImagePtr src, gdRectPtr src_area, const double affine[6]);
+BGD_DECLARE(int) gdTransformAffineCopy(gdImagePtr dst, int dst_x, int dst_y, const gdImagePtr src, gdRectPtr src_region, const double affine[6]);
+/*
+gdTransformAffineCopy(gdImagePtr dst, int x0, int y0, int x1, int y1,
+ const gdImagePtr src, int src_width, int src_height,
+ const double affine[6]);
+*/
+BGD_DECLARE(int) gdTransformAffineBoundingBox(gdRectPtr src, const double affine[6], gdRectPtr bbox);
+
+/**
+ * Group: Image Comparison
+ *
+ * Constants:
+ * GD_CMP_IMAGE - Actual image IS different
+ * GD_CMP_NUM_COLORS - Number of colors in pallette differ
+ * GD_CMP_COLOR - Image colors differ
+ * GD_CMP_SIZE_X - Image width differs
+ * GD_CMP_SIZE_Y - Image heights differ
+ * GD_CMP_TRANSPARENT - Transparent color differs
+ * GD_CMP_BACKGROUND - Background color differs
+ * GD_CMP_INTERLACE - Interlaced setting differs
+ * GD_CMP_TRUECOLOR - Truecolor vs palette differs
+ *
+ * See also:
+ * - <gdImageCompare>
+ */
+#define GD_CMP_IMAGE 1
+#define GD_CMP_NUM_COLORS 2
+#define GD_CMP_COLOR 4
+#define GD_CMP_SIZE_X 8
+#define GD_CMP_SIZE_Y 16
+#define GD_CMP_TRANSPARENT 32
+#define GD_CMP_BACKGROUND 64
+#define GD_CMP_INTERLACE 128
+#define GD_CMP_TRUECOLOR 256
+
+/* resolution affects ttf font rendering, particularly hinting */
+#define GD_RESOLUTION 96 /* pixels per inch */
+
+
+/* Version information functions */
+BGD_DECLARE(int) gdMajorVersion(void);
+BGD_DECLARE(int) gdMinorVersion(void);
+BGD_DECLARE(int) gdReleaseVersion(void);
+BGD_DECLARE(const char *) gdExtraVersion(void);
+BGD_DECLARE(const char *) gdVersionString(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* newfangled special effects */
+//#include "gdfx.h"
+
+#endif /* GD_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libmscgen/gd_color.c b/libmscgen/gd_color.c
new file mode 100644
index 0000000..ba0efd8
--- /dev/null
+++ b/libmscgen/gd_color.c
@@ -0,0 +1,35 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gd.h"
+#include "gd_color.h"
+
+/**
+ * The threshold method works relatively well but it can be improved.
+ * Maybe L*a*b* and Delta-E will give better results (and a better
+ * granularity).
+ */
+int gdColorMatch(gdImagePtr im, int col1, int col2, float threshold)
+{
+ const int dr = gdImageRed(im, col1) - gdImageRed(im, col2);
+ const int dg = gdImageGreen(im, col1) - gdImageGreen(im, col2);
+ const int db = gdImageBlue(im, col1) - gdImageBlue(im, col2);
+ const int da = gdImageAlpha(im, col1) - gdImageAlpha(im, col2);
+ const int dist = dr * dr + dg * dg + db * db + da * da;
+
+ return (100.0 * dist / 195075) < threshold;
+}
+
+/*
+ * To be implemented when we have more image formats.
+ * Buffer like gray8 gray16 or rgb8 will require some tweak
+ * and can be done in this function (called from the autocrop
+ * function. (Pierre)
+ */
+#if 0
+static int colors_equal (const int col1, const in col2)
+{
+
+}
+#endif
diff --git a/libmscgen/gd_color.h b/libmscgen/gd_color.h
new file mode 100644
index 0000000..08b06ce
--- /dev/null
+++ b/libmscgen/gd_color.h
@@ -0,0 +1,14 @@
+#ifndef GD_COLOR_H
+#define GD_COLOR_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ int gdColorMatch(gdImagePtr im, int col1, int col2, float threshold);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmscgen/gd_errors.h b/libmscgen/gd_errors.h
new file mode 100644
index 0000000..4ecee94
--- /dev/null
+++ b/libmscgen/gd_errors.h
@@ -0,0 +1,46 @@
+#ifndef GD_ERRORS_H
+#define GD_ERRORS_H
+
+#ifndef _WIN32
+# include <syslog.h>
+#else
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number). Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code. This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+# define LOG_EMERG 0 /* system is unusable */
+# define LOG_ALERT 1 /* action must be taken immediately */
+# define LOG_CRIT 2 /* critical conditions */
+# define LOG_ERR 3 /* error conditions */
+# define LOG_WARNING 4 /* warning conditions */
+# define LOG_NOTICE 5 /* normal but significant condition */
+# define LOG_INFO 6 /* informational */
+# define LOG_DEBUG 7 /* debug-level messages */
+#endif
+
+/*
+LOG_EMERG system is unusable
+LOG_ALERT action must be taken immediately
+LOG_CRIT critical conditions
+LOG_ERR error conditions
+LOG_WARNING warning conditions
+LOG_NOTICE normal, but significant, condition
+LOG_INFO informational message
+LOG_DEBUG debug-level message
+*/
+
+#define GD_ERROR LOG_ERR
+#define GD_WARNING LOG_WARNING
+#define GD_NOTICE LOG_NOTICE
+#define GD_INFO LOG_INFO
+#define GD_DEBUG LOG_DEBUG
+
+void gd_error(const char *format, ...);
+void gd_error_ex(int priority, const char *format, ...);
+
+#endif
diff --git a/libmscgen/gd_intern.h b/libmscgen/gd_intern.h
new file mode 100644
index 0000000..2e7264b
--- /dev/null
+++ b/libmscgen/gd_intern.h
@@ -0,0 +1,78 @@
+#ifndef GD_INTERN_H
+#define GD_INTERN_H
+
+#include <limits.h>
+#include <stdint.h>
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# elif defined(MAX_PATH)
+# define MAXPATHLEN MAX_PATH
+# else
+# if defined(__GNU__)
+# define MAXPATHLEN 4096
+# else
+# define MAXPATHLEN 256 /* Should be safe for any weird systems that do not define it */
+# endif
+# endif
+#endif
+
+#include "gd.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
+#ifndef MAX
+#define MAX(a,b) ((a)<(b)?(b):(a))
+#endif
+#define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
+
+
+typedef enum {
+ HORIZONTAL,
+ VERTICAL,
+} gdAxis;
+
+/* Convert a double to an unsigned char, rounding to the nearest
+ * integer and clamping the result between 0 and max. The absolute
+ * value of clr must be less than the maximum value of an unsigned
+ * short. */
+static inline unsigned char
+uchar_clamp(double clr, unsigned char max) {
+ unsigned short result;
+
+ //assert(fabs(clr) <= SHRT_MAX);
+
+ /* Casting a negative float to an unsigned short is undefined.
+ * However, casting a float to a signed truncates toward zero and
+ * casting a negative signed value to an unsigned of the same size
+ * results in a bit-identical value (assuming twos-complement
+ * arithmetic). This is what we want: all legal negative values
+ * for clr will be greater than 255. */
+
+ /* Convert and clamp. */
+ result = (unsigned short)(short)(clr + 0.5);
+ if (result > max) {
+ result = (clr < 0) ? 0 : max;
+ }/* if */
+
+ return result;
+}/* uchar_clamp*/
+
+
+/* Internal prototypes: */
+
+/* gd_rotate.c */
+gdImagePtr gdImageRotate90(gdImagePtr src, int ignoretransparent);
+gdImagePtr gdImageRotate180(gdImagePtr src, int ignoretransparent);
+gdImagePtr gdImageRotate270(gdImagePtr src, int ignoretransparent);
+
+
+
+
+
+
+#endif
+
diff --git a/libmscgen/gd_lodepng.c b/libmscgen/gd_lodepng.c
new file mode 100644
index 0000000..b8ed22b
--- /dev/null
+++ b/libmscgen/gd_lodepng.c
@@ -0,0 +1,35 @@
+#include "gd.h"
+#include "lodepng.h"
+
+BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * outFile)
+{
+ unsigned char *buffer;
+ size_t bufferSize;
+ int **ptpixels = im->tpixels;
+ unsigned char *pixelBuffer = (unsigned char *)malloc(3*im->sx*im->sy);
+ unsigned char *pOut = pixelBuffer;
+ int x,y;
+ for (y=0;y<im->sy;y++)
+ {
+ int *pThisRow = *ptpixels++;
+ for (x=0;x<im->sx;x++)
+ {
+ int thisPixel = *pThisRow++;
+ *pOut++ = gdTrueColorGetRed(thisPixel);
+ *pOut++ = gdTrueColorGetGreen(thisPixel);
+ *pOut++ = gdTrueColorGetBlue(thisPixel);
+ }
+ }
+ // TODO: convert ptPixels into pixelBuffer...
+ LodePNG_Encoder encoder;
+ LodePNG_Encoder_init(&encoder);
+ encoder.infoPng.color.colorType = 2; // 2=RGB 24 bit
+ encoder.infoRaw.color.colorType = 2; // 2=RGB 24 bit
+ LodePNG_encode(&encoder, &buffer, &bufferSize, pixelBuffer, im->sx, im->sy);
+ // write bufferSize bytes from buffer into outFile
+ fwrite(buffer,1,bufferSize,outFile);
+ LodePNG_Encoder_cleanup(&encoder);
+ free(buffer);
+ free(pixelBuffer);
+}
+
diff --git a/libmscgen/gd_security.c b/libmscgen/gd_security.c
new file mode 100644
index 0000000..0051ebf
--- /dev/null
+++ b/libmscgen/gd_security.c
@@ -0,0 +1,32 @@
+/*
+ * gd_security.c
+ *
+ * Implements buffer overflow check routines.
+ *
+ * Written 2004, Phil Knirsch.
+ * Based on netpbm fixes by Alan Cox.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "gd.h"
+#include "gd_errors.h"
+
+int overflow2(int a, int b)
+{
+ if(a <= 0 || b <= 0) {
+ gd_error_ex(GD_WARNING, "one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully\n");
+ return 1;
+ }
+ if(a > INT_MAX / b) {
+ gd_error_ex(GD_WARNING, "product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/libmscgen/gdfonts.c b/libmscgen/gdfonts.c
new file mode 100644
index 0000000..e184e36
--- /dev/null
+++ b/libmscgen/gdfonts.c
@@ -0,0 +1,3890 @@
+/*
+ This is a header file for gd font, generated using
+ bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz
+ from bdf font
+ -misc-fixed-medium-r-semicondensed-sans-12-116-75-75-c-60-iso8859-2
+ at Thu Jan 8 14:13:20 1998.
+ No copyright info was found in the original bdf.
+ */
+
+/**
+ * File: Small Font
+ *
+ * A small ISO-8859-2 raster font (7x13 pixels).
+ *
+ * The font is supposed to be used with <gdImageChar> and <gdImageString>
+ * and their variants.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gdfonts.h"
+
+char gdFontSmallData[] = {
+ /* Char 0 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 1 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 2 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1, 0,
+
+ /* Char 3 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 4 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 5 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 6 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 7 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 8 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 9 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 10 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 11 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 12 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 13 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 14 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 15 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 16 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 17 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 18 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 19 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 20 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 21 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 22 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 23 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 24 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 25 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 26 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 27 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 28 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 29 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 30 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 31 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 32 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 33 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 34 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 35 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 36 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 37 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 38 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 39 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 40 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 41 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 42 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 43 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 44 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 45 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 46 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 47 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 48 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 49 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 50 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 51 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 52 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 53 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 54 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 55 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 56 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 57 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 58 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 59 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 60 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 61 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 62 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 63 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 64 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 65 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 66 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 67 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 68 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 69 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 70 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 71 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 72 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 73 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 74 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 75 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 76 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 77 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 1, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 78 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 79 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 80 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 81 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 82 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 83 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 84 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 85 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 86 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 87 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 88 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 89 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 90 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 91 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 92 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 93 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 94 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 95 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 96 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 97 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 98 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 99 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 100 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 101 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 102 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 103 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+
+ /* Char 104 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 105 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 106 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+
+ /* Char 107 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 108 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 109 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 110 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 111 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 112 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+
+ /* Char 113 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+
+ /* Char 114 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 115 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 116 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 117 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 118 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 119 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 120 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 121 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+
+ /* Char 122 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 123 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 124 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 125 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 126 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 127 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 128 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 129 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 130 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 131 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 132 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 133 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 134 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 135 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 136 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 137 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 138 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 139 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 140 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 141 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 142 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 143 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 144 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 145 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 146 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 147 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 148 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 149 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 150 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 151 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 152 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 153 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 154 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 155 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 156 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 157 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 158 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 159 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 160 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 161 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 1,
+
+ /* Char 162 */
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 163 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 164 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 165 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 166 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 167 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 168 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 169 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 170 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+
+ /* Char 171 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 172 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 173 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 174 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 175 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 176 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 177 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 1,
+
+ /* Char 178 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+
+ /* Char 179 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 180 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 181 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1,
+ 0, 1, 1, 0, 0, 1,
+ 0, 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 182 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 183 */
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 184 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+
+ /* Char 185 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 186 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+
+ /* Char 187 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 188 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 189 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 190 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 191 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 192 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 193 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 194 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 195 */
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 196 */
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 197 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 198 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 199 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+
+ /* Char 200 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 201 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 202 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+
+ /* Char 203 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 204 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 205 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 206 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 207 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 208 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 209 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 210 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 211 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 212 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 213 */
+ 0, 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 214 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 215 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 216 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 217 */
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 218 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 219 */
+ 0, 0, 1, 0, 0, 1,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 220 */
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 221 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 222 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 223 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 224 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 225 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 226 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 227 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 228 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 229 */
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 230 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 231 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+
+ /* Char 232 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 233 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 234 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+
+ /* Char 235 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 236 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 237 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 238 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 239 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 240 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 1, 1,
+ 0, 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 241 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 242 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 243 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 244 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 245 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 246 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 247 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 248 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 249 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 250 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 251 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 252 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+ /* Char 253 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0, 0,
+
+ /* Char 254 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+
+ /* Char 255 */
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+
+
+};
+
+gdFont gdFontSmallRep = {
+ 256,
+ 0,
+ 6,
+ 13,
+ gdFontSmallData
+};
+
+BGD_EXPORT_DATA_PROT gdFontPtr gdFontSmall = &gdFontSmallRep;
+
+/**
+ * Function: gdFontGetSmall
+ *
+ * Returns the built-in small font.
+ */
+BGD_DECLARE(gdFontPtr)
+gdFontGetSmall (void)
+{
+ return gdFontSmall;
+}
+
+/* This file has not been truncated. */
diff --git a/libmscgen/gdfonts.h b/libmscgen/gdfonts.h
new file mode 100644
index 0000000..b5127e9
--- /dev/null
+++ b/libmscgen/gdfonts.h
@@ -0,0 +1,27 @@
+#ifndef _GDFONTS_H_
+#define _GDFONTS_H_ 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ This is a header file for gd font, generated using
+ bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz
+ from bdf font
+ -misc-fixed-medium-r-semicondensed-sans-12-116-75-75-c-60-iso8859-2
+ at Thu Jan 8 14:13:20 1998.
+ No copyright info was found in the original bdf.
+ */
+
+#include "gd.h"
+
+extern BGD_EXPORT_DATA_PROT gdFontPtr gdFontSmall;
+BGD_DECLARE(gdFontPtr) gdFontGetSmall(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmscgen/gdfontt.c b/libmscgen/gdfontt.c
new file mode 100644
index 0000000..e7bb345
--- /dev/null
+++ b/libmscgen/gdfontt.c
@@ -0,0 +1,2613 @@
+
+
+/*
+ This is a header file for gd font, generated using
+ bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz
+ from bdf font
+ -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-2
+ at Thu Jan 8 13:49:54 1998.
+ The original bdf was holding following copyright:
+ "Libor Skarvada, libor@informatics.muni.cz"
+ */
+
+/**
+ * File: Tiny Font
+ *
+ * A very small ISO-8859-2 raster font (5x8 pixels).
+ *
+ * The font is supposed to be used with <gdImageChar> and <gdImageString>
+ * and their variants.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gdfontt.h"
+
+char gdFontTinyData[] = {
+ /* Char 0 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 1 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 2 */
+ 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+
+ /* Char 3 */
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+
+ /* Char 4 */
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 0, 1, 1, 1,
+ 1, 0, 1, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 5 */
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 1,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 1,
+
+ /* Char 6 */
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 7 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 8 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 9 */
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, 1,
+
+ /* Char 10 */
+ 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+
+ /* Char 11 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 12 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 13 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 14 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 15 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 16 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 17 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 18 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 19 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 20 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 21 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 22 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 23 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 24 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 25 */
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 26 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 27 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 28 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 29 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 30 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 1, 0, 0, 1,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 1,
+ 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 31 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 32 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 33 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 34 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 35 */
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 36 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 1,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 37 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 1,
+ 1, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 1,
+ 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0,
+
+ /* Char 38 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0,
+
+ /* Char 39 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 40 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 41 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 42 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 43 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 44 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 45 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 46 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 47 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 48 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 49 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 50 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 51 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 52 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 53 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 54 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 55 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 56 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 57 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 58 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 59 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+
+ /* Char 60 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 61 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 62 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 63 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 64 */
+ 0, 0, 1, 1, 0,
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 1,
+ 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+
+ /* Char 65 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 66 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 67 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 68 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 69 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 70 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 71 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 72 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 73 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 74 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 75 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 76 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 77 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 78 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 79 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 80 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 81 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+
+ /* Char 82 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 83 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 84 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 85 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 86 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 87 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 88 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 89 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 90 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 91 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 92 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+
+ /* Char 93 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 94 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 95 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+
+ /* Char 96 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 97 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 98 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 99 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 100 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 101 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 102 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 103 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 104 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 105 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 106 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+
+ /* Char 107 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 108 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 109 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1,
+ 1, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+
+ /* Char 110 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 111 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 112 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+
+ /* Char 113 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 0, 1, 0,
+
+ /* Char 114 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 115 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 116 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 117 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 118 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 119 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1,
+ 1, 0, 1, 0, 1,
+ 1, 0, 1, 0, 1,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 120 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 121 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 122 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 123 */
+ 0, 0, 1, 1, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 124 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 125 */
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 126 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 127 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 128 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 129 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 130 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 131 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 132 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 133 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 134 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 135 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 136 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 137 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 138 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 139 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 140 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 141 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 142 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 143 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 144 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 145 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 146 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 147 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 148 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 149 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 150 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 151 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 152 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 153 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 154 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 155 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 156 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 157 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 158 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 159 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 160 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 161 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 0, 0, 1, 1,
+
+ /* Char 162 */
+ 1, 0, 0, 0, 1,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 163 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0,
+
+ /* Char 164 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 165 */
+ 0, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 166 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 167 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 1, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 168 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 169 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 170 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+
+ /* Char 171 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 172 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 173 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 174 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 175 */
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 176 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 177 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 1, 1,
+
+ /* Char 178 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 1, 1,
+
+ /* Char 179 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 180 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 181 */
+ 0, 0, 0, 1, 1,
+ 1, 1, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 182 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 183 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 184 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 185 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 186 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+
+ /* Char 187 */
+ 0, 0, 0, 1, 1,
+ 0, 1, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 188 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 189 */
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 190 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 191 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 192 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 193 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 194 */
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 195 */
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 196 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 197 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 198 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 199 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 1, 0, 0, 0,
+
+ /* Char 200 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 201 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 202 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 1,
+
+ /* Char 203 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 204 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 205 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 206 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 207 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 208 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 209 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 210 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 1, 1, 1, 0,
+ 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 211 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 212 */
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 213 */
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 214 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 215 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 216 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 217 */
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 218 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 219 */
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 220 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 221 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 222 */
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+
+ /* Char 223 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 0, 0, 0,
+
+ /* Char 224 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 225 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 226 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 227 */
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 228 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 229 */
+ 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 230 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 231 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 1, 1, 0, 0,
+
+ /* Char 232 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 233 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 234 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 1,
+
+ /* Char 235 */
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 236 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 1, 0,
+ 1, 1, 0, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 237 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 238 */
+ 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 239 */
+ 0, 0, 0, 1, 1,
+ 0, 0, 1, 0, 1,
+ 0, 0, 1, 0, 1,
+ 0, 1, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 240 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 1, 1,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 241 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 242 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 243 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 244 */
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 245 */
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 246 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 247 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 248 */
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0,
+ 1, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 249 */
+ 0, 1, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 250 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 251 */
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 252 */
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 1, 1, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+
+ /* Char 253 */
+ 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 1, 0, 0, 1, 0,
+ 1, 0, 0, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 254 */
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0,
+ 1, 1, 1, 0, 0,
+ 0, 1, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0,
+ 0, 1, 1, 0, 0,
+
+ /* Char 255 */
+ 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+
+};
+
+gdFont gdFontTinyRep = {
+ 256,
+ 0,
+ 5,
+ 8,
+ gdFontTinyData
+};
+
+BGD_EXPORT_DATA_PROT gdFontPtr gdFontTiny = &gdFontTinyRep;
+
+/**
+ * Function: gdFontGetTiny
+ *
+ * Returns the built-in tiny font.
+ */
+BGD_DECLARE(gdFontPtr)
+gdFontGetTiny (void)
+{
+ return gdFontTiny;
+}
+
+/* This file has not been truncated. */
diff --git a/libmscgen/gdfontt.h b/libmscgen/gdfontt.h
new file mode 100644
index 0000000..d61b01f
--- /dev/null
+++ b/libmscgen/gdfontt.h
@@ -0,0 +1,28 @@
+#ifndef _GDFONTT_H_
+#define _GDFONTT_H_ 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ This is a header file for gd font, generated using
+ bdftogd version 0.5 by Jan Pazdziora, adelton@fi.muni.cz
+ from bdf font
+ -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-2
+ at Thu Jan 8 13:49:54 1998.
+ The original bdf was holding following copyright:
+ "Libor Skarvada, libor@informatics.muni.cz"
+ */
+
+#include "gd.h"
+
+extern BGD_EXPORT_DATA_PROT gdFontPtr gdFontTiny;
+BGD_DECLARE(gdFontPtr) gdFontGetTiny(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmscgen/gdhelpers.c b/libmscgen/gdhelpers.c
new file mode 100644
index 0000000..20fff5c
--- /dev/null
+++ b/libmscgen/gdhelpers.c
@@ -0,0 +1,118 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gd.h"
+#include "gdhelpers.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <ctype.h>
+
+/* TBB: gd_strtok_r is not portable; provide an implementation */
+
+#define SEP_TEST (separators[*((unsigned char *) s)])
+
+char *
+gd_strtok_r (char *s, char *sep, char **state)
+{
+ char separators[256];
+ char *result = 0;
+ memset (separators, 0, sizeof (separators));
+ while (*sep) {
+ separators[*((unsigned char *) sep)] = 1;
+ sep++;
+ }
+ if (!s) {
+ /* Pick up where we left off */
+ s = *state;
+ }
+ /* 1. EOS */
+ if (!(*s)) {
+ *state = s;
+ return 0;
+ }
+ /* 2. Leading separators, if any */
+ if (SEP_TEST) {
+ do {
+ s++;
+ } while (SEP_TEST);
+ /* 2a. EOS after separators only */
+ if (!(*s)) {
+ *state = s;
+ return 0;
+ }
+ }
+ /* 3. A token */
+ result = s;
+ do {
+ /* 3a. Token at end of string */
+ if (!(*s)) {
+ *state = s;
+ return result;
+ }
+ s++;
+ } while (!SEP_TEST);
+ /* 4. Terminate token and skip trailing separators */
+ *s = '\0';
+ do {
+ s++;
+ } while (SEP_TEST);
+ /* 5. Return token */
+ *state = s;
+ return result;
+}
+
+void * gdCalloc (size_t nmemb, size_t size)
+{
+ return calloc (nmemb, size);
+}
+
+void *
+gdMalloc (size_t size)
+{
+ return malloc (size);
+}
+
+void *
+gdRealloc (void *ptr, size_t size)
+{
+ return realloc (ptr, size);
+}
+
+void *
+gdReallocEx (void *ptr, size_t size)
+{
+ void *newPtr = gdRealloc (ptr, size);
+ if (!newPtr && ptr)
+ gdFree(ptr);
+ return newPtr;
+}
+
+/*
+ Function: gdFree
+
+ Frees memory that has been allocated by libgd functions.
+
+ Unless more specialized functions exists (for instance, <gdImageDestroy>),
+ all memory that has been allocated by public libgd functions has to be
+ freed by calling <gdFree>, and not by free(3), because libgd internally
+ doesn't use alloc(3) and friends but rather its own allocation functions,
+ which are, however, not publicly available.
+
+ Parameters:
+
+ ptr - Pointer to the memory space to free. If it is NULL, no operation is
+ performed.
+
+ Returns:
+
+ Nothing.
+*/
+BGD_DECLARE(void) gdFree (void *ptr)
+{
+ free (ptr);
+}
+
+
diff --git a/libmscgen/gdhelpers.h b/libmscgen/gdhelpers.h
new file mode 100644
index 0000000..2a96b8b
--- /dev/null
+++ b/libmscgen/gdhelpers.h
@@ -0,0 +1,76 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GDHELPERS_H
+#define GDHELPERS_H 1
+
+ /* sys/types.h is needed for size_t on Sparc-SunOS-4.1 */
+#ifndef _WIN32_WCE
+#include <sys/types.h>
+#else
+#include <stdlib.h>
+#endif /* _WIN32_WCE */
+
+ /* TBB: strtok_r is not universal; provide an implementation of it. */
+
+ char * gd_strtok_r (char *s, char *sep, char **state);
+
+ /* These functions wrap memory management. gdFree is
+ in gd.h, where callers can utilize it to correctly
+ free memory allocated by these functions with the
+ right version of free(). */
+ void *gdCalloc (size_t nmemb, size_t size);
+ void *gdMalloc (size_t size);
+ void *gdRealloc (void *ptr, size_t size);
+ /* The extended version of gdReallocEx will free *ptr if the
+ * realloc fails */
+ void *gdReallocEx (void *ptr, size_t size);
+
+ /* Returns nonzero if multiplying the two quantities will
+ result in integer overflow. Also returns nonzero if
+ either quantity is negative. By Phil Knirsch based on
+ netpbm fixes by Alan Cox. */
+
+ int overflow2(int a, int b);
+
+ /* 2.0.16: portable mutex support for thread safety. */
+#if defined(CPP_SHARP)
+# define gdMutexDeclare(x)
+# define gdMutexSetup(x)
+# define gdMutexShutdown(x)
+# define gdMutexLock(x)
+# define gdMutexUnlock(x)
+#elif defined(_WIN32)
+ /* 2.0.18: must include windows.h to get CRITICAL_SECTION. */
+# include <windows.h>
+# define gdMutexDeclare(x) CRITICAL_SECTION x
+# define gdMutexSetup(x) InitializeCriticalSection(&x)
+# define gdMutexShutdown(x) DeleteCriticalSection(&x)
+# define gdMutexLock(x) EnterCriticalSection(&x)
+# define gdMutexUnlock(x) LeaveCriticalSection(&x)
+#elif defined(HAVE_PTHREAD)
+# include <pthread.h>
+# define gdMutexDeclare(x) pthread_mutex_t x
+# define gdMutexSetup(x) pthread_mutex_init(&x, 0)
+# define gdMutexShutdown(x) pthread_mutex_destroy(&x)
+# define gdMutexLock(x) pthread_mutex_lock(&x)
+# define gdMutexUnlock(x) pthread_mutex_unlock(&x)
+#else
+# define gdMutexDeclare(x)
+# define gdMutexSetup(x)
+# define gdMutexShutdown(x)
+# define gdMutexLock(x)
+# define gdMutexUnlock(x)
+#endif /* _WIN32 || HAVE_PTHREAD */
+
+#define DPCM2DPI(dpcm) (unsigned int)((dpcm)*2.54 + 0.5)
+#define DPM2DPI(dpm) (unsigned int)((dpm)*0.0254 + 0.5)
+#define DPI2DPCM(dpi) (unsigned int)((dpi)/2.54 + 0.5)
+#define DPI2DPM(dpi) (unsigned int)((dpi)/0.0254 + 0.5)
+
+#endif /* GDHELPERS_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libmscgen/gdtables.c b/libmscgen/gdtables.c
new file mode 100644
index 0000000..7753b21
--- /dev/null
+++ b/libmscgen/gdtables.c
@@ -0,0 +1,726 @@
+
+const int gdCosT[] = {
+ 1024,
+ 1023,
+ 1023,
+ 1022,
+ 1021,
+ 1020,
+ 1018,
+ 1016,
+ 1014,
+ 1011,
+ 1008,
+ 1005,
+ 1001,
+ 997,
+ 993,
+ 989,
+ 984,
+ 979,
+ 973,
+ 968,
+ 962,
+ 955,
+ 949,
+ 942,
+ 935,
+ 928,
+ 920,
+ 912,
+ 904,
+ 895,
+ 886,
+ 877,
+ 868,
+ 858,
+ 848,
+ 838,
+ 828,
+ 817,
+ 806,
+ 795,
+ 784,
+ 772,
+ 760,
+ 748,
+ 736,
+ 724,
+ 711,
+ 698,
+ 685,
+ 671,
+ 658,
+ 644,
+ 630,
+ 616,
+ 601,
+ 587,
+ 572,
+ 557,
+ 542,
+ 527,
+ 512,
+ 496,
+ 480,
+ 464,
+ 448,
+ 432,
+ 416,
+ 400,
+ 383,
+ 366,
+ 350,
+ 333,
+ 316,
+ 299,
+ 282,
+ 265,
+ 247,
+ 230,
+ 212,
+ 195,
+ 177,
+ 160,
+ 142,
+ 124,
+ 107,
+ 89,
+ 71,
+ 53,
+ 35,
+ 17,
+ 0,
+ -17,
+ -35,
+ -53,
+ -71,
+ -89,
+ -107,
+ -124,
+ -142,
+ -160,
+ -177,
+ -195,
+ -212,
+ -230,
+ -247,
+ -265,
+ -282,
+ -299,
+ -316,
+ -333,
+ -350,
+ -366,
+ -383,
+ -400,
+ -416,
+ -432,
+ -448,
+ -464,
+ -480,
+ -496,
+ -512,
+ -527,
+ -542,
+ -557,
+ -572,
+ -587,
+ -601,
+ -616,
+ -630,
+ -644,
+ -658,
+ -671,
+ -685,
+ -698,
+ -711,
+ -724,
+ -736,
+ -748,
+ -760,
+ -772,
+ -784,
+ -795,
+ -806,
+ -817,
+ -828,
+ -838,
+ -848,
+ -858,
+ -868,
+ -877,
+ -886,
+ -895,
+ -904,
+ -912,
+ -920,
+ -928,
+ -935,
+ -942,
+ -949,
+ -955,
+ -962,
+ -968,
+ -973,
+ -979,
+ -984,
+ -989,
+ -993,
+ -997,
+ -1001,
+ -1005,
+ -1008,
+ -1011,
+ -1014,
+ -1016,
+ -1018,
+ -1020,
+ -1021,
+ -1022,
+ -1023,
+ -1023,
+ -1024,
+ -1023,
+ -1023,
+ -1022,
+ -1021,
+ -1020,
+ -1018,
+ -1016,
+ -1014,
+ -1011,
+ -1008,
+ -1005,
+ -1001,
+ -997,
+ -993,
+ -989,
+ -984,
+ -979,
+ -973,
+ -968,
+ -962,
+ -955,
+ -949,
+ -942,
+ -935,
+ -928,
+ -920,
+ -912,
+ -904,
+ -895,
+ -886,
+ -877,
+ -868,
+ -858,
+ -848,
+ -838,
+ -828,
+ -817,
+ -806,
+ -795,
+ -784,
+ -772,
+ -760,
+ -748,
+ -736,
+ -724,
+ -711,
+ -698,
+ -685,
+ -671,
+ -658,
+ -644,
+ -630,
+ -616,
+ -601,
+ -587,
+ -572,
+ -557,
+ -542,
+ -527,
+ -512,
+ -496,
+ -480,
+ -464,
+ -448,
+ -432,
+ -416,
+ -400,
+ -383,
+ -366,
+ -350,
+ -333,
+ -316,
+ -299,
+ -282,
+ -265,
+ -247,
+ -230,
+ -212,
+ -195,
+ -177,
+ -160,
+ -142,
+ -124,
+ -107,
+ -89,
+ -71,
+ -53,
+ -35,
+ -17,
+ 0,
+ 17,
+ 35,
+ 53,
+ 71,
+ 89,
+ 107,
+ 124,
+ 142,
+ 160,
+ 177,
+ 195,
+ 212,
+ 230,
+ 247,
+ 265,
+ 282,
+ 299,
+ 316,
+ 333,
+ 350,
+ 366,
+ 383,
+ 400,
+ 416,
+ 432,
+ 448,
+ 464,
+ 480,
+ 496,
+ 512,
+ 527,
+ 542,
+ 557,
+ 572,
+ 587,
+ 601,
+ 616,
+ 630,
+ 644,
+ 658,
+ 671,
+ 685,
+ 698,
+ 711,
+ 724,
+ 736,
+ 748,
+ 760,
+ 772,
+ 784,
+ 795,
+ 806,
+ 817,
+ 828,
+ 838,
+ 848,
+ 858,
+ 868,
+ 877,
+ 886,
+ 895,
+ 904,
+ 912,
+ 920,
+ 928,
+ 935,
+ 942,
+ 949,
+ 955,
+ 962,
+ 968,
+ 973,
+ 979,
+ 984,
+ 989,
+ 993,
+ 997,
+ 1001,
+ 1005,
+ 1008,
+ 1011,
+ 1014,
+ 1016,
+ 1018,
+ 1020,
+ 1021,
+ 1022,
+ 1023,
+ 1023
+};
+
+const int gdSinT[] = {
+ 0,
+ 17,
+ 35,
+ 53,
+ 71,
+ 89,
+ 107,
+ 124,
+ 142,
+ 160,
+ 177,
+ 195,
+ 212,
+ 230,
+ 247,
+ 265,
+ 282,
+ 299,
+ 316,
+ 333,
+ 350,
+ 366,
+ 383,
+ 400,
+ 416,
+ 432,
+ 448,
+ 464,
+ 480,
+ 496,
+ 512,
+ 527,
+ 542,
+ 557,
+ 572,
+ 587,
+ 601,
+ 616,
+ 630,
+ 644,
+ 658,
+ 671,
+ 685,
+ 698,
+ 711,
+ 724,
+ 736,
+ 748,
+ 760,
+ 772,
+ 784,
+ 795,
+ 806,
+ 817,
+ 828,
+ 838,
+ 848,
+ 858,
+ 868,
+ 877,
+ 886,
+ 895,
+ 904,
+ 912,
+ 920,
+ 928,
+ 935,
+ 942,
+ 949,
+ 955,
+ 962,
+ 968,
+ 973,
+ 979,
+ 984,
+ 989,
+ 993,
+ 997,
+ 1001,
+ 1005,
+ 1008,
+ 1011,
+ 1014,
+ 1016,
+ 1018,
+ 1020,
+ 1021,
+ 1022,
+ 1023,
+ 1023,
+ 1024,
+ 1023,
+ 1023,
+ 1022,
+ 1021,
+ 1020,
+ 1018,
+ 1016,
+ 1014,
+ 1011,
+ 1008,
+ 1005,
+ 1001,
+ 997,
+ 993,
+ 989,
+ 984,
+ 979,
+ 973,
+ 968,
+ 962,
+ 955,
+ 949,
+ 942,
+ 935,
+ 928,
+ 920,
+ 912,
+ 904,
+ 895,
+ 886,
+ 877,
+ 868,
+ 858,
+ 848,
+ 838,
+ 828,
+ 817,
+ 806,
+ 795,
+ 784,
+ 772,
+ 760,
+ 748,
+ 736,
+ 724,
+ 711,
+ 698,
+ 685,
+ 671,
+ 658,
+ 644,
+ 630,
+ 616,
+ 601,
+ 587,
+ 572,
+ 557,
+ 542,
+ 527,
+ 512,
+ 496,
+ 480,
+ 464,
+ 448,
+ 432,
+ 416,
+ 400,
+ 383,
+ 366,
+ 350,
+ 333,
+ 316,
+ 299,
+ 282,
+ 265,
+ 247,
+ 230,
+ 212,
+ 195,
+ 177,
+ 160,
+ 142,
+ 124,
+ 107,
+ 89,
+ 71,
+ 53,
+ 35,
+ 17,
+ 0,
+ -17,
+ -35,
+ -53,
+ -71,
+ -89,
+ -107,
+ -124,
+ -142,
+ -160,
+ -177,
+ -195,
+ -212,
+ -230,
+ -247,
+ -265,
+ -282,
+ -299,
+ -316,
+ -333,
+ -350,
+ -366,
+ -383,
+ -400,
+ -416,
+ -432,
+ -448,
+ -464,
+ -480,
+ -496,
+ -512,
+ -527,
+ -542,
+ -557,
+ -572,
+ -587,
+ -601,
+ -616,
+ -630,
+ -644,
+ -658,
+ -671,
+ -685,
+ -698,
+ -711,
+ -724,
+ -736,
+ -748,
+ -760,
+ -772,
+ -784,
+ -795,
+ -806,
+ -817,
+ -828,
+ -838,
+ -848,
+ -858,
+ -868,
+ -877,
+ -886,
+ -895,
+ -904,
+ -912,
+ -920,
+ -928,
+ -935,
+ -942,
+ -949,
+ -955,
+ -962,
+ -968,
+ -973,
+ -979,
+ -984,
+ -989,
+ -993,
+ -997,
+ -1001,
+ -1005,
+ -1008,
+ -1011,
+ -1014,
+ -1016,
+ -1018,
+ -1020,
+ -1021,
+ -1022,
+ -1023,
+ -1023,
+ -1024,
+ -1023,
+ -1023,
+ -1022,
+ -1021,
+ -1020,
+ -1018,
+ -1016,
+ -1014,
+ -1011,
+ -1008,
+ -1005,
+ -1001,
+ -997,
+ -993,
+ -989,
+ -984,
+ -979,
+ -973,
+ -968,
+ -962,
+ -955,
+ -949,
+ -942,
+ -935,
+ -928,
+ -920,
+ -912,
+ -904,
+ -895,
+ -886,
+ -877,
+ -868,
+ -858,
+ -848,
+ -838,
+ -828,
+ -817,
+ -806,
+ -795,
+ -784,
+ -772,
+ -760,
+ -748,
+ -736,
+ -724,
+ -711,
+ -698,
+ -685,
+ -671,
+ -658,
+ -644,
+ -630,
+ -616,
+ -601,
+ -587,
+ -572,
+ -557,
+ -542,
+ -527,
+ -512,
+ -496,
+ -480,
+ -464,
+ -448,
+ -432,
+ -416,
+ -400,
+ -383,
+ -366,
+ -350,
+ -333,
+ -316,
+ -299,
+ -282,
+ -265,
+ -247,
+ -230,
+ -212,
+ -195,
+ -177,
+ -160,
+ -142,
+ -124,
+ -107,
+ -89,
+ -71,
+ -53,
+ -35,
+ -17
+};
diff --git a/libmscgen/mscgen_adraw.c b/libmscgen/mscgen_adraw.c
new file mode 100644
index 0000000..8e638a5
--- /dev/null
+++ b/libmscgen/mscgen_adraw.c
@@ -0,0 +1,140 @@
+/***************************************************************************
+ *
+ * $Id: adraw.c 161 2010-10-26 20:17:16Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+/***************************************************************************
+ * Include Files
+ ***************************************************************************/
+
+#include "mscgen_config.h"
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "mscgen_adraw_int.h"
+
+/***************************************************************************
+ * Functions
+ ***************************************************************************/
+
+Boolean ADrawOpen(unsigned int w,
+ unsigned int h,
+ const char *file,
+ const char *fontName,
+ ADrawOutputType type,
+ struct ADrawTag *outContext)
+{
+ assert(outContext);
+
+ switch(type)
+ {
+ case ADRAW_FMT_NULL:
+ return NullInit(outContext);
+
+ case ADRAW_FMT_PNG:
+#if !defined(REMOVE_PNG_OUTPUT)
+ return GdoInit(w, h, file, fontName, outContext);
+#else
+ fprintf(stderr, "Built with REMOVE_PNG_OUTPUT; PNG output is not supported\n");
+ return FALSE;
+#endif
+ case ADRAW_FMT_EPS:
+ return PsInit(w, h, file, outContext);
+
+ case ADRAW_FMT_SVG:
+ return SvgInit(w, h, file, outContext);
+
+ default:
+ return FALSE;
+ }
+}
+
+
+ADrawColour ADrawGetColour(const char *colour)
+{
+ assert(colour != NULL);
+
+ /* Check if an RGB value has been specified */
+ if(*colour == '#')
+ {
+ unsigned int c = ADRAW_COL_BLACK;
+
+ if(sscanf(&colour[1], "%x", &c) == 1)
+ {
+ return (ADrawColour)c;
+ }
+ }
+ else /* Check for name matches */
+ {
+ static const struct
+ {
+ char *name;
+ ADrawColour col;
+ }
+ colourMap[] =
+ {
+ { "WHITE", ADRAW_COL_WHITE },
+ { "BLACK", ADRAW_COL_BLACK },
+ { "RED", ADRAW_COL_RED },
+ { "ORANGE", ADRAW_COL_ORANGE },
+ { "YELLOW", ADRAW_COL_YELLOW },
+ { "GREEN", ADRAW_COL_GREEN },
+ { "BLUE", ADRAW_COL_BLUE },
+ { "INDIGO", ADRAW_COL_INDIGO },
+ { "VIOLET", ADRAW_COL_VIOLET },
+ { "SILVER", ADRAW_COL_SILVER },
+ { "LIME", ADRAW_COL_LIME },
+ { "GRAY", ADRAW_COL_GRAY },
+ { "OLIVE", ADRAW_COL_OLIVE },
+ { "MAROON", ADRAW_COL_MAROON },
+ { "NAVY", ADRAW_COL_NAVY },
+ { "PURPLE", ADRAW_COL_PURPLE },
+ { "TEAL", ADRAW_COL_TEAL },
+ { "FUCHSIA", ADRAW_COL_FUCHSIA },
+ { "AQUA", ADRAW_COL_AQUA }
+ };
+
+ unsigned int t;
+
+ for(t = 0; t < sizeof(colourMap) / sizeof(colourMap[0]); t++)
+ {
+ if(strcasecmp(colour, colourMap[t].name) == 0)
+ {
+ return colourMap[t].col;
+ }
+ }
+ }
+
+ /* Default to black if all else failed */
+ return ADRAW_COL_BLACK;
+}
+
+
+void ADrawComputeArcPoint(float cx, float cy, float w, float h, float degrees,
+ unsigned int *x, unsigned int *y)
+{
+ float rad = (float)((degrees * M_PI) / 180.0f);
+
+ *x = (unsigned int)round(cx + ((w / 2.0f) * cos(rad)));
+ *y = (unsigned int)round(cy + ((h / 2.0f) * sin(rad)));
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_adraw.h b/libmscgen/mscgen_adraw.h
new file mode 100644
index 0000000..b2e11a3
--- /dev/null
+++ b/libmscgen/mscgen_adraw.h
@@ -0,0 +1,300 @@
+/***************************************************************************
+ *
+ * $Id: adraw.h 161 2010-10-26 20:17:16Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#ifndef MSCGEN_ADRAW_H
+#define MSCGEN_ADRAW_H
+
+#include "mscgen_bool.h"
+
+/***************************************************************************
+ * Types
+ ***************************************************************************/
+
+/** Output format types.
+ * Enumerated types for output formats.
+ */
+typedef enum
+{
+ /** Null output format.
+ * This allows all the graphics commands to be called, but does nothing.
+ */
+ ADRAW_FMT_NULL = 0,
+
+ /** Generate a PNG. */
+ ADRAW_FMT_PNG,
+
+ /** Generate Encapsulated Postscript. */
+ ADRAW_FMT_EPS,
+
+ /** Scalable Vector Graphics. */
+ ADRAW_FMT_SVG
+}
+ADrawOutputType;
+
+
+/** Supported colours.
+ * Enumerated type to describe colours.
+ *
+ * The 16 basic HTML colours at http://www.w3.org/TR/html4/types.html#h-6.5
+ * are defined as well as a few other common colour names.
+ */
+typedef enum
+{
+ ADRAW_COL_WHITE = 0x00ffffff,
+ ADRAW_COL_BLACK = 0x00000000,
+ ADRAW_COL_RED = 0x00ff0000,
+ ADRAW_COL_ORANGE = 0x00ffb000,
+ ADRAW_COL_YELLOW = 0x00ffff00,
+ ADRAW_COL_GREEN = 0x0000ff00,
+ ADRAW_COL_BLUE = 0x000000ff,
+ ADRAW_COL_INDIGO = 0x00440088,
+ ADRAW_COL_VIOLET = 0x00d02090,
+ ADRAW_COL_SILVER = 0x00C0C0C0,
+ ADRAW_COL_LIME = 0x0000FF00,
+ ADRAW_COL_GRAY = 0x00808080,
+ ADRAW_COL_OLIVE = 0x00808000,
+ ADRAW_COL_MAROON = 0x00800000,
+ ADRAW_COL_NAVY = 0x00000080,
+ ADRAW_COL_PURPLE = 0x00800080,
+ ADRAW_COL_TEAL = 0x00008080,
+ ADRAW_COL_FUCHSIA = 0x00FF00FF,
+ ADRAW_COL_AQUA = 0x0000FFFF,
+
+ ADRAW_COL_INVALID = 0xff000000,
+}
+ADrawColour;
+
+
+/** Basic font sizes.
+ * Enumerated type for different font sizes.
+ */
+typedef enum
+{
+ ADRAW_FONT_TINY = 0,
+ ADRAW_FONT_SMALL
+}
+ADrawFontSize;
+
+
+/** An ADraw context.
+ * This is the main structure used for accessing ADraw functions.
+ * ADrawOpen() returns an instance of this structure that can then be used
+ * to render to some device. Once drawing is complete, ADrawClose() should
+ * be called to reclaim resources and finalise any output.
+ *
+ * All the functions assume that 0,0 is in the top-left corner of the image,
+ * and that the dimensions grow towards w,y at the bottom-right corner.
+ */
+typedef struct ADrawTag
+{
+ /** Draw a line.
+ * Draw a solid straight line between two points.
+ * \param ctx The drawing context.
+ * \param x1 The first x co-ordinate,
+ * \param y1 The first y co-ordinate,
+ * \param x2 The second x co-ordinate,
+ * \param y2 The second y co-ordinate,
+ */
+ void (*line) (struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2);
+
+ /** Draw a dotted line.
+ * Draw a dotted straight line between two points.
+ * \param ctx The drawing context.
+ * \param x1 The first x co-ordinate,
+ * \param y1 The first y co-ordinate,
+ * \param x2 The second x co-ordinate,
+ * \param y2 The second y co-ordinate,
+ */
+ void (*dottedLine) (struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2);
+
+ /** Left aligned text.
+ * Write a single line of text that will end at some co-ordinates.
+ * \param ctx The drawing context.
+ * \param x The position at which the text should terminate.
+ * \param y The position above which the text will lie.
+ * \param string The string to write.
+ */
+ void (*textL) (struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string);
+
+ /** Center aligned text.
+ * Write a single line of text that will center on some co-ordinates.
+ * \param ctx The drawing context.
+ * \param x The position at which the text should be centered.
+ * \param y The position above which the text will lie.
+ * \param string The string to write.
+ */
+ void (*textC) (struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string);
+
+ /** Right aligned text.
+ * Write a single line of text that will start at some co-ordinates.
+ * \param ctx The drawing context.
+ * \param x The position at which the text should start.
+ * \param y The position above which the text will lie.
+ * \param string The string to write.
+ */
+ void (*textR) (struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string);
+
+ /** Determine the width of some string.
+ * \param ctx The drawing context.
+ * \param string The string for which the width should be determined.
+ * \returns The width of the passed string as it would be rendered
+ * by the current drawing context.
+ */
+ unsigned int (*textWidth) (struct ADrawTag *ctx,
+ const char *string);
+
+ /** Determine the height of text in the current font.
+ * \param ctx The drawing context.
+ *
+ */
+ int (*textHeight) (struct ADrawTag *ctx);
+
+ void (*filledRectangle)(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2);
+
+ void (*filledTriangle)(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2,
+ unsigned int x3,
+ unsigned int y3);
+
+ void (*filledCircle)(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ unsigned int r);
+
+ /** Draw an arc.
+ * This draws an arc centred at (cx,cy) which fits in a box of \a w by \a h.
+ * The arc is drawn from \a s degrees to \a e degrees.
+ * \note 0 degrees points east on the page and 90 degrees is south.
+ *
+ */
+ void (*arc) (struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e);
+
+ void (*dottedArc) (struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e);
+
+ void (*setPen) (struct ADrawTag *ctx,
+ ADrawColour col);
+
+ void (*setBgPen) (struct ADrawTag *ctx,
+ ADrawColour col);
+
+ void (*setFontSize) (struct ADrawTag *ctx,
+ ADrawFontSize size);
+
+ Boolean (*close) (struct ADrawTag *context);
+
+ /* Internal context, not accessible by the user */
+ void *internal;
+}
+ADraw;
+
+/***************************************************************************
+ * Functions
+ ***************************************************************************/
+
+/** Create a new drawing context.
+ * This will create a drawing context with some dimensions, and some format.
+ * After this has been called, the function pointers in the returned structure
+ * can be called together with a pointer to the structure itself to cause
+ * image functions to be executed.
+ *
+ * \param[in] w The width of the output image.
+ * \param[in] h The height of the ouput image.
+ * \param[in] file The file to which the image should be written.
+ * \param[in] fontName The name of the font to use for rendering.
+ * \param[in] type The output type to generate.
+ * \param[in, out] *outContext Pointer to an \a ADraw structure to populate
+ * with values.
+ * \retval Boolean On error, #FALSE will be returned.
+ */
+Boolean ADrawOpen(unsigned int w,
+ unsigned int h,
+ const char *file,
+ const char *fontName,
+ ADrawOutputType type,
+ struct ADrawTag *outContext);
+
+/** Given a string name for a colour, return the corresponding ADrawColour.
+ *
+ * \param[in] colour The string representation of the colour that is sought.
+ */
+ADrawColour ADrawGetColour(const char *colour);
+
+/** Compute the position of a point on an arc.
+ * This allows co-ordinates on arc drawn using arc() or dottedArc() to be
+ * computed. The centre and bounding box for the arc are supplied as well
+ * as an angular offset.
+ *
+ * \param[in] cx Center of the arc.
+ * \param[in] cy Center of the arc.
+ * \param[in] w Arc x-diameter (width).
+ * \param[in] h Arc y-diameter (height).
+ * \param[in] degrees Position on the arc to be returned.
+ * \param[in,out] x Pointer to fill with x coordinate.
+ * \param[in,out] y Pointer to fill with y coordinate.
+ */
+void ADrawComputeArcPoint(float cx,
+ float cy,
+ float w,
+ float h,
+ float degrees,
+ unsigned int *x,
+ unsigned int *y);
+
+#endif /* MSCGEN_ADRAW_H */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_adraw_int.h b/libmscgen/mscgen_adraw_int.h
new file mode 100644
index 0000000..6f79ca4
--- /dev/null
+++ b/libmscgen/mscgen_adraw_int.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ *
+ * $Id: adraw_int.h 115 2010-08-19 09:58:45Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#ifndef MSCGEN_ADRAW_INT_H
+#define MSCGEN_ADRAW_INT_H
+
+#include "mscgen_adraw.h"
+
+/***************************************************************************
+ * Preprocessor Macros
+ ***************************************************************************/
+
+/* Define macro to supress unused parameter warnings */
+#ifndef UNUSED
+# ifdef __GNUC__
+# define UNUSED __attribute__((unused))
+# else
+# define UNUSED
+# endif
+#endif
+
+/***************************************************************************
+ * Functions
+ ***************************************************************************/
+
+Boolean NullInit(struct ADrawTag *outContext);
+
+Boolean GdoInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ const char *fontName,
+ struct ADrawTag *outContext);
+
+Boolean PsInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ struct ADrawTag *outContext);
+
+Boolean SvgInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ struct ADrawTag *outContext);
+
+#endif /* MSCGEN_ADRAW_INT_H */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_api.c b/libmscgen/mscgen_api.c
new file mode 100644
index 0000000..0f6052a
--- /dev/null
+++ b/libmscgen/mscgen_api.c
@@ -0,0 +1,1874 @@
+#include "mscgen_api.h"
+#include "mscgen_config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include "mscgen_lexer.h"
+#include "mscgen_adraw.h"
+#include "mscgen_msc.h"
+#include "mscgen_safe.h"
+
+/***************************************************************************
+ * Macro definitions
+ ***************************************************************************/
+
+#define M_Max(a, b) (((a) > (b)) ? (a) : (b))
+#define M_Min(a, b) (((a) < (b)) ? (a) : (b))
+
+/***************************************************************************
+ * Types
+ ***************************************************************************/
+
+/** Structure for holding global options.
+ * This structure groups all the options that affect the text output into
+ * one structure.
+ */
+typedef struct GlobalOptionsTag
+{
+ /** Ideal width of output canvas.
+ * If this value allows the entitySpacing to be increased, then
+ * entitySpacing will be set to the larger value of it's original
+ * value and idealCanvasWidth / number of entities.
+ */
+ unsigned int idealCanvasWidth;
+
+ /** Horizontal spacing between entities. */
+ unsigned int entitySpacing;
+
+ /** Gap at the top of the page. */
+ unsigned int entityHeadGap;
+
+ /** Vertical spacing between arcs. */
+ unsigned int arcSpacing;
+
+ /** Arc gradient.
+ * Y offset of arc head, relative to tail, in pixels.
+ */
+ int arcGradient;
+
+ /** Gap between adjacent boxes. */
+ unsigned int boxSpacing;
+
+ /** Minimum distance between box edges and text. */
+ unsigned int boxInternalBorder;
+
+ /** Radius of rounded box corner arcs. */
+ unsigned int rboxArc;
+
+ /** Size of 'corner' added to note boxes. */
+ unsigned int noteCorner;
+
+ /** Anguluar box slope in pixels. */
+ unsigned int aboxSlope;
+
+ /** If TRUE, wrap arc text as well as box contents. */
+ Boolean wordWrapArcLabels;
+
+ /** Horizontal width of the arrow heads. */
+ unsigned int arrowWidth;
+
+ /** Vertical depth of the arrow heads. */
+ unsigned int arrowHeight;
+
+ /** Height of an arc which loops back to itself. */
+ unsigned int loopArcHeight;
+
+ /** Horizontal gap between text and horizontal lines. */
+ unsigned int textHGapPre;
+
+ /** Horizontal gap between text and horizontal lines. */
+ unsigned int textHGapPost;
+}
+GlobalOptions;
+
+/** Information about each out row.
+ */
+typedef struct
+{
+ /** Minimum Y value. */
+ unsigned int ymin;
+
+ /** Y position of the arc on the row. */
+ unsigned int arcliney;
+
+ /** Maximum Y value. */
+ unsigned int ymax;
+
+ /** Maximum lines of text on the row. */
+ unsigned int maxTextLines;
+}
+RowInfo;
+
+
+typedef struct ContextTag
+{
+ GlobalOptions opts;
+ ADraw drw;
+} Context;
+
+
+/***************************************************************************
+ * Local Variables.
+ ***************************************************************************/
+
+static const GlobalOptions gDefaultOpts =
+{
+ 600, /* idealCanvasWidth */
+
+ 80, /* entitySpacing */
+ 20, /* entityHeadGap */
+ 6, /* arcSpacing */
+ 0, /* arcGradient */
+ 8, /* boxSpacing */
+ 4, /* boxInternalBorder */
+ 6, /* rboxArc */
+ 12, /* noteCorner */
+ 6, /* aboxSlope */
+ FALSE, /* wordWrapArcLabels */
+
+ /* Arrow options */
+ 10, 6,
+
+ /* loopArcHeight */
+ 12,
+
+ /* textHGapPre, textHGapPost */
+ 2, 2
+};
+
+
+/***************************************************************************
+ * Functions
+ ***************************************************************************/
+
+/** Count the number of lines in some string.
+ * This counts line breaks that are written as a literal '\n' in the line to
+ * determine how many lines of output are needed.
+ *
+ * \param[in] l Pointer to the input string to inspect.
+ * \returns The count of '\n' characters appearing in the input string + 1.
+ */
+static unsigned int countLines(const char *l)
+{
+ unsigned int c = 1;
+
+ do
+ {
+ c++;
+
+ l = strstr(l, "\\n");
+ if (l) l += 2;
+ } while (l != NULL);
+
+ return c;
+}
+
+/** Check if some arc type indicates a box.
+ */
+static Boolean isBoxArc(const MscArcType a)
+{
+ return a == MSC_ARC_BOX || a == MSC_ARC_RBOX ||
+ a == MSC_ARC_ABOX || a== MSC_ARC_NOTE;
+}
+
+/** Get the skip value in pixels for some the current arc in the Msc.
+ */
+static int getArcGradient(Context *ctx, Msc m, const RowInfo *rowInfo, unsigned int row)
+{
+ const char *s = MscGetCurrentArcAttrib(m, MSC_ATTR_ARC_SKIP);
+ unsigned int v = ctx->opts.arcGradient;
+
+ if (s != NULL && rowInfo != NULL)
+ {
+ const unsigned int rowCount = MscGetNumArcs(m) - MscGetNumParallelArcs(m);
+ unsigned int skip;
+
+ if (sscanf(s, "%u", &skip) == 1)
+ {
+ unsigned int ystart = rowInfo[row].arcliney;
+ unsigned int yend = rowInfo[M_Min(rowCount - 1, row + skip)].arcliney;
+
+ v += yend - ystart;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Non-integer arcskip value: %s\n", s);
+ }
+ }
+
+ return v;
+}
+
+
+/** Check if some arc name indicates a broadcast entity.
+ */
+static Boolean isBroadcastArc(const char *entity)
+{
+ return entity != NULL && (strcmp(entity, "*") == 0);
+}
+
+/** Free memory allocated for the label lines.
+ */
+static void freeLabelLines(unsigned int n, char **lines)
+{
+ while (n > 0)
+ {
+ n--;
+ free(lines[n]);
+ }
+
+ free(lines);
+}
+
+
+/** Word wrap a line of text until the first line is less than \a width wide.
+ * This removes words from the input line and builds them into a 2nd new
+ * string until the input line is shorter than the supplied width. The
+ * input string is directly truncated, while the remaining characters are
+ * returned in a new memory allocation. On return, the input line of text
+ * will be shorter than \a width, while the newly returned string will contain
+ * all the remaining characters.
+ *
+ * If the input line is already shorter than \a width, the function returns
+ * NULL and does not modify the input line of text.
+ *
+ * \param[in,out] l Input line of text which maybe modified if needed.
+ * \param[in] width Maximum allowable text line width.
+ * \returns NULL if \a l was already less then \a width long,
+ * otherwise a new string giving the remained of the string.
+ */
+static char *splitStringToWidth(Context *ctx, char *l, unsigned int width)
+{
+ char *p = l + strlen(l);
+ char *orig = NULL;
+ int m, n;
+
+ if (ctx->drw.textWidth(&ctx->drw, l) > width)
+ {
+ /* Duplicate the original string */
+ orig = strdup_s(l);
+
+ /* Now remove words from the line until it fits the available width */
+ do
+ {
+ /* Skip back 1 word */
+ while (!isspace(*p) && p > l)
+ {
+ p--;
+ }
+
+ if (p > l)
+ {
+ *p = '\0';
+ }
+ }
+ while (ctx->drw.textWidth(&ctx->drw, l) > width && p > l);
+
+ /* Check if the first word is bigger than the available space;
+ * we need to hyphenate in this case.
+ */
+ if (p == l)
+ {
+ const unsigned int hyphenWidth = ctx->drw.textWidth(&ctx->drw, "-");
+
+ /* Find the end of the first word */
+ while (!isspace(*p) && *p != '\0')
+ {
+ p++;
+ }
+
+ /* Start removing characters from the word */
+ do
+ {
+ *p = '\0';
+ p--;
+ }
+ while (ctx->drw.textWidth(&ctx->drw, l) + hyphenWidth > width && p > l);
+
+ /* Add a hyphen */
+ *p = '-';
+ }
+
+ /* Copy the remaining line to the start of the string */
+ m = 0;
+ n = (p - l);
+
+ while (isspace(orig[n]) && orig[n] != '\0')
+ {
+ n++;
+ }
+
+ do
+ {
+ orig[m++] = orig[n++];
+ }
+ while (orig[m - 1] != '\0');
+ }
+
+ return orig;
+}
+
+
+/** Split an input arc label into lines, word-wrapping if needed.
+ * This takes the literal label supplied from the input and splits it into an
+ * array of char * text lines. Splitting is first done according to literal
+ * '\n' character sequences added by the user, then according to word wrapping
+ * to fit available space, if appropriate.
+ *
+ * \param[in] m The MSC for which the lines are to be split.
+ * \param[in] arcType The type of the arc being labelled.
+ * \param[in,out] lines Pointer to be filled with output line array.
+ * \param[in] label Original arc label from input file.
+ * \param[in] startCol Column in which the arc starts.
+ * \param[in] endCol Column in which the arc ends, or -1 for broadcast arcs.
+ *
+ * \note The returned strings and array must be free()'d. freeLabelLines() can
+ * be used for this purpose.
+ */
+static unsigned int computeLabelLines(Context *ctx,
+ Msc m,
+ const MscArcType arcType,
+ char ***lines,
+ const char *label,
+ int startCol,
+ int endCol)
+{
+ unsigned int width;
+ unsigned int nAllocLines = 8;
+ char **retLines = malloc_s(sizeof(char *) * nAllocLines);
+ unsigned int c = 0;
+
+ assert(startCol >= 0 && startCol < (signed)MscGetNumEntities(m));
+ assert(startCol >= -1 && startCol < (signed)MscGetNumEntities(m));
+
+ /* Compute available width for text */
+ if (isBoxArc(arcType) || ctx->opts.wordWrapArcLabels)
+ {
+ if (endCol == -1)
+ {
+ /* This is a special case for a broadcast arc */
+ width = ctx->opts.entitySpacing * MscGetNumEntities(m);
+ }
+ else if (startCol < endCol)
+ {
+ width = ctx->opts.entitySpacing * (1 + (endCol - startCol));
+ }
+ else
+ {
+ width = ctx->opts.entitySpacing * (1 + (startCol - endCol));
+ }
+
+ /* Reduce the width due to the box borders */
+ if (isBoxArc(arcType))
+ {
+ width -= (ctx->opts.boxSpacing + ctx->opts.boxInternalBorder) * 2;
+ }
+
+ if (arcType == MSC_ARC_NOTE)
+ {
+ width -= ctx->opts.noteCorner;
+ }
+ }
+ else
+ {
+ width = UINT_MAX;
+ }
+
+ /* Split the input label into lines */
+ while (label != NULL)
+ {
+ /* First split around user specified lines with literal '\n' */
+ char *nextLine = strstr(label, "\\n");
+ if (nextLine)
+ {
+ const int lineLen = nextLine - label;
+
+ /* Allocate storage and duplicate the line */
+ retLines[c] = malloc_s(lineLen + 1);
+ memcpy(retLines[c], label, lineLen);
+ retLines[c][lineLen] = '\0';
+
+ /* Advance the label */
+ label = nextLine + 2;
+ }
+ else
+ {
+ /* Duplicate the final line */
+ retLines[c] = strdup_s(label);
+ label = NULL;
+ }
+
+ /* Now split the line as required to wrap into the space available */
+ do
+ {
+ /* Check if more storage maybe needed */
+ if (c + 2 >= nAllocLines)
+ {
+ nAllocLines += 8;
+ retLines = realloc_s(retLines, sizeof(char *) * nAllocLines);
+ }
+
+ retLines[c + 1] = splitStringToWidth(ctx, retLines[c], width);
+ c++;
+ }
+ while (retLines[c] != NULL);
+ }
+
+ /* Return the array of lines and the count */
+ *lines = retLines;
+
+ return c;
+}
+
+
+
+/** Compute the output canvas size required for some MSC.
+ * This computes the dimensions for the canvas as well as the height for each
+ * row.
+ *
+ * \param[in] m The MSC to analyse.
+ * \param[in,out] w Pointer to be filled with the output width.
+ * \param[in,out] h Pointer to be filled with the output height.
+ * \returns An array giving the height of each row.
+ */
+static RowInfo *computeCanvasSize(Context *ctx,
+ Msc m,
+ unsigned int *w,
+ unsigned int *h)
+{
+ const unsigned int rowCount = MscGetNumArcs(m) - MscGetNumParallelArcs(m);
+ const unsigned int textHeight = ctx->drw.textHeight(&ctx->drw);
+ RowInfo *rowHeight;
+ unsigned int nextYmin, ymin, ymax, yskipmax, row;
+
+ /* Allocate storage for the height of each row */
+ rowHeight = zalloc_s(sizeof(RowInfo) * rowCount);
+ row = 0;
+
+ nextYmin = ymin = ctx->opts.entityHeadGap;
+ yskipmax = 0;
+
+ MscResetArcIterator(m);
+ do
+ {
+ const MscArcType arcType = MscGetCurrentArcType(m);
+ const int arcGradient = isBoxArc(arcType) ? 0 : getArcGradient(ctx, m, NULL, 0);
+ char **arcLabelLines = NULL;
+ unsigned int arcLabelLineCount = 0;
+ int startCol = -1, endCol = -1;
+
+ if (arcType == MSC_ARC_PARALLEL)
+ {
+ assert(row > 0);
+
+ row--;
+
+ ymin = rowHeight[row].ymin;
+ nextYmin = rowHeight[row].ymax;
+ }
+ else
+ {
+ /* Get the entity indices */
+ if (arcType != MSC_ARC_DISCO && arcType != MSC_ARC_DIVIDER && arcType != MSC_ARC_SPACE)
+ {
+ startCol = MscGetEntityIndex(m, MscGetCurrentArcSource(m));
+ endCol = MscGetEntityIndex(m, MscGetCurrentArcDest(m));
+ }
+ else
+ {
+ /* Discontinuity or parallel arc spans whole chart */
+ startCol = 0;
+ endCol = MscGetNumEntities(m) - 1;
+ }
+
+ /* Work out how the label fits the gap between entities */
+ arcLabelLineCount = computeLabelLines(ctx, m, arcType, &arcLabelLines,
+ MscGetCurrentArcAttrib(m, MSC_ATTR_LABEL),
+ startCol, endCol);
+
+ assert(row < rowCount);
+
+ /* Update the max line count for the row */
+ if (arcLabelLineCount > rowHeight[row].maxTextLines)
+ {
+ rowHeight[row].maxTextLines = arcLabelLineCount;
+ }
+
+ freeLabelLines(arcLabelLineCount, arcLabelLines);
+
+ /* Compute the height of this arc */
+ if (arcType != MSC_ARC_DISCO && arcType != MSC_ARC_DIVIDER && arcType != MSC_ARC_SPACE)
+ {
+ ymax = ymin + ctx->opts.arcSpacing;
+ ymax += (M_Max(rowHeight[row].maxTextLines, 2) * textHeight);
+ }
+ else
+ {
+ ymax = ymin + ctx->opts.arcSpacing;
+ ymax += (M_Max(rowHeight[row].maxTextLines, 1) * textHeight);
+ }
+
+ /* Update next potential row start */
+ if (ymax > nextYmin)
+ {
+ nextYmin = ymax;
+ }
+
+ /* Compute the dimensions for the completed row */
+ rowHeight[row].ymin = ymin;
+ rowHeight[row].ymax = nextYmin - ctx->opts.arcSpacing;
+ rowHeight[row].arcliney = rowHeight[row].ymin + (rowHeight[row].ymax - rowHeight[row].ymin) / 2;
+ row++;
+
+ /* Start new row */
+ ymin = nextYmin;
+ }
+
+ /* Keep a track of where the gradient may cause the graph to end */
+ if (ymax + arcGradient > ymax)
+ {
+ yskipmax = ymax + arcGradient;
+ }
+
+ }
+ while (MscNextArc(m));
+
+ if (ymax < yskipmax)
+ ymax = yskipmax;
+
+ /* Set the return values */
+ *w = MscGetNumEntities(m) * ctx->opts.entitySpacing;
+ *h = ymax;
+
+ return rowHeight;
+}
+
+/** Add a point to the output imagemap.
+ * If \a ismap and \a url are non-NULL, this function will add a rectangle
+ * to the imagemap according to the parameters passed.
+ *
+ * \param ismap The file to which the imagemap should be rendered.
+ * \param url The URL to which the imagemap area should link.
+ * \param x1 The x coordinate for the upper left point.
+ * \param y2 The y coordinate for the upper left point.
+ * \param x2 The x coordinate for the lower right point.
+ * \param y2 The y coordinate for the lower right point.
+ */
+static void ismapRect(FILE *ismap,
+ const char *url,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ if(ismap && url)
+ {
+ assert(x1 <= x2); assert(y1 <= y2);
+
+ fprintf(ismap,
+ "rect %s %d,%d %d,%d\n",
+ url,
+ x1, y1,
+ x2, y2);
+ }
+#if 0
+ /* For debug render a cross onto the output */
+ drw.line(&drw, x1, y1, x2, y2);
+ drw.line(&drw, x2, y1, x1, y2);
+#endif
+}
+
+
+/** Get some line from a string containing '\n' delimiters.
+ * Given a string that contains literal '\n' delimiters, return a subset in
+ * a passed buffer that gives the nth line.
+ *
+ * \param[in] string The string to parse.
+ * \param[in] line The line number to return from the string, which should
+ * count from 0.
+ * \param[in] out Pointer to a buffer to fill with line data.
+ * \param[in] outLen The length of the buffer pointed to by \a out, in bytes.
+ * \returns A pointer to \a out.
+ */
+static char *getLine(const char *string,
+ unsigned int line,
+ char *const out,
+ const unsigned int outLen)
+{
+ const char *lineStart, *lineEnd;
+ unsigned int lineLen;
+
+ /* Setup for the loop */
+ lineEnd = NULL;
+ line++;
+
+ do
+ {
+ /* Check if this is the first or a repeat iteration */
+ if(lineEnd)
+ {
+ lineStart = lineEnd + 2;
+ }
+ else
+ {
+ lineStart = string;
+ }
+
+ /* Search for next delimited */
+ lineEnd = strstr(lineStart, "\\n");
+
+ line--;
+ }
+ while (line > 0 && lineEnd != NULL);
+
+ /* Determine the length of the line */
+ if(lineEnd != NULL)
+ {
+ lineLen = lineEnd - lineStart;
+ }
+ else
+ {
+ lineLen = strlen(string) - (lineStart - string);
+ }
+
+ /* Clamp the length to the buffer */
+ if(lineLen > outLen - 1)
+ {
+ lineLen = outLen - 1;
+ }
+
+ /* Copy desired characters */
+ memcpy(out, lineStart, lineLen);
+
+ /* NULL terminate */
+ out[lineLen] = '\0';
+
+ return out;
+}
+
+
+/** Render some entity text.
+ * Draw the text for some entity.
+ * \param ismap If not \a NULL, write an ismap description here.
+ * \param x The x position at which the entity text should be centered.
+ * \param y The y position where the text should be placed.
+ * \param entLabel The label to render, which maybe \a NULL in which case
+ * no ouput is produced.
+ * \param entUrl The URL for rendering the label as a hyperlink. This
+ * maybe \a NULL if not required.
+ * \param entId The text identifier for the arc.
+ * \param entIdUrl The URL for rendering the test identifier as a hyperlink.
+ * This maybe \a NULL if not required.
+ * \param entColour The text colour name or specification for the entity text.
+ * If NULL, use default colouring scheme.
+ * \param entBgColour The text background colour name or specification for the
+ * entity text. If NULL, use default colouring scheme.
+ */
+static void entityText(Context *ctx,
+ FILE *ismap,
+ unsigned int x,
+ unsigned int y,
+ const char *entLabel,
+ const char *entUrl,
+ const char *entId,
+ const char *entIdUrl,
+ const char *entColour,
+ const char *entBgColour)
+{
+ if(entLabel)
+ {
+ const unsigned int lines = countLines(entLabel);
+ unsigned int l;
+ char lineBuffer[1024];
+
+ /* Adjust y to be above the writing line */
+ y -= ctx->drw.textHeight(&ctx->drw) * (lines - 1);
+
+ for (l = 0; l < lines - 1; l++)
+ {
+ char *lineLabel = getLine(entLabel, l, lineBuffer, sizeof(lineBuffer));
+ unsigned int width = ctx->drw.textWidth(&ctx->drw, lineLabel);
+
+ /* Push text down one line */
+ y += ctx->drw.textHeight(&ctx->drw);
+
+ /* Check if a URL is associated */
+ if(entUrl)
+ {
+ /* If no explict colour has been set, make URLS blue */
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLUE);
+
+ /* Image map output */
+ ismapRect(ismap,
+ entUrl,
+ x - (width / 2), y - ctx->drw.textHeight(&ctx->drw),
+ x + (width / 2), y);
+ }
+
+ /* Set to the explicit colours if directed */
+ if(entColour != NULL)
+ {
+ ctx->drw.setPen(&ctx->drw, ADrawGetColour(entColour));
+ }
+
+ if(entBgColour != NULL)
+ {
+ ctx->drw.setBgPen(&ctx->drw, ADrawGetColour(entBgColour));
+ }
+
+ /* Render text and restore pen */
+ ctx->drw.textC (&ctx->drw, x, y, lineLabel);
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ ctx->drw.setBgPen(&ctx->drw, ADRAW_COL_WHITE);
+
+ /* Render the Id of the title, if specified and for first line only */
+ if(entId && l == 0)
+ {
+ unsigned int idwidth;
+ int idx, idy;
+
+ idy = y - ctx->drw.textHeight(&ctx->drw);
+ idx = x + (width / 2);
+
+ ctx->drw.setFontSize(&ctx->drw, ADRAW_FONT_TINY);
+
+ idwidth = ctx->drw.textWidth(&ctx->drw, entId);
+ idy += (ctx->drw.textHeight(&ctx->drw) + 1) / 2;
+
+ if(entIdUrl)
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLUE);
+ ctx->drw.textR (&ctx->drw, idx, idy, entId);
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+
+ /* Image map output */
+ ismapRect(ismap,
+ entIdUrl,
+ idx, idy - ctx->drw.textHeight(&ctx->drw),
+ idx + idwidth, idy);
+ }
+ else
+ {
+ ctx->drw.textR(&ctx->drw, idx, idy, entId);
+ }
+
+ ctx->drw.setFontSize(&ctx->drw, ADRAW_FONT_SMALL);
+ }
+ }
+ }
+}
+
+/** Draw vertical lines stemming from entities.
+ * This function will draw a single segment of the vertical line that
+ * drops from an entity.
+ *
+ * \param m The \a Msc for which the lines are drawn
+ * \param ymin Top of the row.
+ * \param ymax Bottom of the row.
+ * \param dotted If #TRUE, produce a dotted line, otherwise solid.
+ * \param colourRefs Colour references for each entity.
+ */
+static void entityLines(Context *ctx,
+ Msc m,
+ const unsigned int ymin,
+ const unsigned int ymax,
+ Boolean dotted,
+ const ADrawColour *colourRefs)
+{
+ unsigned int t;
+
+ for (t = 0; t < MscGetNumEntities(m); t++)
+ {
+ unsigned int x = (ctx->opts.entitySpacing / 2) + (ctx->opts.entitySpacing * t);
+
+ ctx->drw.setPen(&ctx->drw, colourRefs[t]);
+
+ if(dotted)
+ {
+ ctx->drw.dottedLine(&ctx->drw, x, ymin, x, ymax);
+ }
+ else
+ {
+ ctx->drw.line(&ctx->drw, x, ymin, x, ymax);
+ }
+ }
+
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+
+}
+
+/** Draw an arrow pointing to the right.
+ * \param x The x co-ordinate for the end point for the arrow head.
+ * \param y The y co-ordinate for the end point for the arrow head.
+ * \param type The arc type, which controls the format of the arrow head.
+ */
+static void arrowR(Context *ctx,
+ unsigned int x,
+ unsigned int y,
+ MscArcType type)
+{
+ switch(type)
+ {
+ case MSC_ARC_SIGNAL: /* Unfilled half */
+ ctx->drw.line(&ctx->drw,
+ x, y,
+ x - ctx->opts.arrowWidth, y + ctx->opts.arrowHeight);
+ break;
+
+ case MSC_ARC_DOUBLE:
+ case MSC_ARC_METHOD: /* Filled */
+ case MSC_ARC_RETVAL: /* Filled, dotted arc (not rendered here) */
+ ctx->drw.filledTriangle(&ctx->drw,
+ x, y,
+ x - ctx->opts.arrowWidth, y + ctx->opts.arrowHeight,
+ x - ctx->opts.arrowWidth, y - ctx->opts.arrowHeight);
+ break;
+
+ case MSC_ARC_CALLBACK: /* Non-filled */
+ ctx->drw.line(&ctx->drw,
+ x, y,
+ x - ctx->opts.arrowWidth, y + ctx->opts.arrowHeight);
+ ctx->drw.line(&ctx->drw,
+ x - ctx->opts.arrowWidth, y - ctx->opts.arrowHeight,
+ x, y);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+
+/** Draw an arrow pointing to the left.
+ * \param x The x co-ordinate for the end point for the arrow head.
+ * \param y The y co-ordinate for the end point for the arrow head.
+ * \param type The arc type, which controls the format of the arrow head.
+ */
+static void arrowL(Context *ctx,
+ unsigned int x,
+ unsigned int y,
+ MscArcType type)
+{
+ switch(type)
+ {
+ case MSC_ARC_SIGNAL: /* Unfilled half */
+ ctx->drw.line(&ctx->drw,
+ x, y,
+ x + ctx->opts.arrowWidth, y + ctx->opts.arrowHeight);
+ break;
+
+ case MSC_ARC_DOUBLE:
+ case MSC_ARC_METHOD: /* Filled */
+ case MSC_ARC_RETVAL: /* Filled, dotted arc (not rendered here) */
+ ctx->drw.filledTriangle(&ctx->drw,
+ x, y,
+ x + ctx->opts.arrowWidth, y + ctx->opts.arrowHeight,
+ x + ctx->opts.arrowWidth, y - ctx->opts.arrowHeight);
+ break;
+
+ case MSC_ARC_CALLBACK: /* Non-filled */
+ ctx->drw.line(&ctx->drw,
+ x, y,
+ x + ctx->opts.arrowWidth, y + ctx->opts.arrowHeight);
+ ctx->drw.line(&ctx->drw,
+ x, y,
+ x + ctx->opts.arrowWidth, y - ctx->opts.arrowHeight);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+
+/** Draw vertical lines and boxes stemming from entities.
+ * \param ymin Top of the row.
+ * \param ymax Bottom of the row.
+ * \param boxStart Column in which the box starts.
+ * \param boxEnd Column in which the box ends.
+ * \param boxType The type of box to draw, MSC_ARC_BOX, MSC_ARC_RBOX etc.
+ * \param lineColour Colour of the lines to use for rendering the box.
+ * \param bgColour Background colour for rendering the box.
+ */
+static void arcBox(Context *ctx,
+ unsigned int ymin,
+ unsigned int ymax,
+ unsigned int boxStart,
+ unsigned int boxEnd,
+ MscArcType boxType,
+ const char *lineColour,
+ const char *bgColour)
+{
+ unsigned int t;
+
+ /* Ensure the start is less than or equal to the end */
+ if(boxStart > boxEnd)
+ {
+ t = boxEnd;
+ boxEnd = boxStart;
+ boxStart = t;
+ }
+
+ /* Now draw the box */
+ unsigned int x1 = (ctx->opts.entitySpacing * boxStart) + ctx->opts.boxSpacing;
+ unsigned int x2 = ctx->opts.entitySpacing * (boxEnd + 1) - ctx->opts.boxSpacing;
+ unsigned int ymid = (ymin + ymax) / 2;
+
+ /* Set colour for the background area */
+ if(bgColour != NULL)
+ {
+ ctx->drw.setPen(&ctx->drw, ADrawGetColour(bgColour));
+ }
+ else
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_WHITE);
+ }
+
+ /* Draw the background to overwrite the entity lines */
+ switch(boxType)
+ {
+ case MSC_ARC_BOX:
+ ctx->drw.filledRectangle(&ctx->drw, x1, ymin, x2, ymax);
+ break;
+
+ case MSC_ARC_RBOX:
+ ctx->drw.filledRectangle(&ctx->drw, x1 + ctx->opts.rboxArc, ymin, x2 - ctx->opts.rboxArc, ymax);
+ ctx->drw.filledRectangle(&ctx->drw, x1, ymin + ctx->opts.rboxArc, x2, ymax - ctx->opts.rboxArc);
+ ctx->drw.filledCircle(&ctx->drw, x1 + ctx->opts.rboxArc, ymin + ctx->opts.rboxArc, ctx->opts.rboxArc);
+ ctx->drw.filledCircle(&ctx->drw, x2 - ctx->opts.rboxArc, ymin + ctx->opts.rboxArc, ctx->opts.rboxArc);
+ ctx->drw.filledCircle(&ctx->drw, x1 + ctx->opts.rboxArc, ymax - ctx->opts.rboxArc, ctx->opts.rboxArc);
+ ctx->drw.filledCircle(&ctx->drw, x2 - ctx->opts.rboxArc, ymax - ctx->opts.rboxArc, ctx->opts.rboxArc);
+ break;
+
+ case MSC_ARC_NOTE:
+ ctx->drw.filledRectangle(&ctx->drw, x1, ymin, x2 - ctx->opts.noteCorner, ymax);
+ ctx->drw.filledRectangle(&ctx->drw, x1, ymin + ctx->opts.noteCorner, x2, ymax);
+ ctx->drw.filledTriangle(&ctx->drw, x2 - ctx->opts.noteCorner, ymin,
+ x2, ymin + ctx->opts.noteCorner,
+ x2 - ctx->opts.noteCorner, ymin + ctx->opts.noteCorner);
+ break;
+
+ case MSC_ARC_ABOX:
+ ctx->drw.filledRectangle(&ctx->drw, x1 + ctx->opts.aboxSlope, ymin, x2 - ctx->opts.aboxSlope, ymax);
+ ctx->drw.filledTriangle(&ctx->drw, x1 + ctx->opts.aboxSlope, ymin,
+ x1 + ctx->opts.aboxSlope, ymax,
+ x1, ymid);
+ ctx->drw.filledTriangle(&ctx->drw, x2 - ctx->opts.aboxSlope, ymin,
+ x2 - ctx->opts.aboxSlope, ymax,
+ x2, ymid);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ /* Setup the colour for rendering the boxes */
+ if(lineColour)
+ {
+ ctx->drw.setPen(&ctx->drw, ADrawGetColour(lineColour));
+ }
+ else
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ }
+
+ /* Draw the outline */
+ switch(boxType)
+ {
+ case MSC_ARC_BOX:
+ ctx->drw.line(&ctx->drw, x1, ymin, x2, ymin);
+ ctx->drw.line(&ctx->drw, x1, ymax, x2, ymax);
+ ctx->drw.line(&ctx->drw, x1, ymin, x1, ymax);
+ ctx->drw.line(&ctx->drw, x2, ymin, x2, ymax);
+ break;
+
+ case MSC_ARC_NOTE:
+ ctx->drw.line(&ctx->drw, x1, ymin, x2 - ctx->opts.noteCorner, ymin);
+ ctx->drw.line(&ctx->drw, x1, ymax, x2, ymax);
+ ctx->drw.line(&ctx->drw, x1, ymin, x1, ymax);
+ ctx->drw.line(&ctx->drw, x2, ymin + ctx->opts.noteCorner, x2, ymax);
+ ctx->drw.line(&ctx->drw, x2 - ctx->opts.noteCorner, ymin,
+ x2, ymin + ctx->opts.noteCorner);
+ ctx->drw.line(&ctx->drw, x2 - ctx->opts.noteCorner, ymin,
+ x2 - ctx->opts.noteCorner, ymin + ctx->opts.noteCorner);
+ ctx->drw.line(&ctx->drw, x2, ymin + ctx->opts.noteCorner,
+ x2 - ctx->opts.noteCorner, ymin + ctx->opts.noteCorner);
+ break;
+
+ case MSC_ARC_RBOX:
+ ctx->drw.line(&ctx->drw, x1 + ctx->opts.rboxArc, ymin, x2 - ctx->opts.rboxArc, ymin);
+ ctx->drw.line(&ctx->drw, x1 + ctx->opts.rboxArc, ymax, x2 - ctx->opts.rboxArc, ymax);
+ ctx->drw.line(&ctx->drw, x1, ymin + ctx->opts.rboxArc, x1, ymax - ctx->opts.rboxArc);
+ ctx->drw.line(&ctx->drw, x2, ymin + ctx->opts.rboxArc, x2, ymax - ctx->opts.rboxArc);
+
+ ctx->drw.arc(&ctx->drw, x1 + ctx->opts.rboxArc,
+ ymin + ctx->opts.rboxArc, ctx->opts.rboxArc * 2, ctx->opts.rboxArc * 2,
+ 180, 270);
+ ctx->drw.arc(&ctx->drw, x2 - ctx->opts.rboxArc,
+ ymin + ctx->opts.rboxArc, ctx->opts.rboxArc * 2, ctx->opts.rboxArc * 2,
+ 270, 0);
+ ctx->drw.arc(&ctx->drw, x2 - ctx->opts.rboxArc,
+ ymax - ctx->opts.rboxArc, ctx->opts.rboxArc * 2, ctx->opts.rboxArc * 2,
+ 0, 90);
+ ctx->drw.arc(&ctx->drw, x1 + ctx->opts.rboxArc,
+ ymax - ctx->opts.rboxArc, ctx->opts.rboxArc * 2, ctx->opts.rboxArc * 2,
+ 90, 180);
+ break;
+
+ case MSC_ARC_ABOX:
+ ctx->drw.line(&ctx->drw, x1 + ctx->opts.aboxSlope, ymin, x2 - ctx->opts.aboxSlope, ymin);
+ ctx->drw.line(&ctx->drw, x1 + ctx->opts.aboxSlope, ymax, x2 - ctx->opts.aboxSlope, ymax);
+ ctx->drw.line(&ctx->drw, x1 + ctx->opts.aboxSlope, ymin, x1, ymid);
+ ctx->drw.line(&ctx->drw, x1, ymid, x1 + ctx->opts.aboxSlope, ymax);
+ ctx->drw.line(&ctx->drw, x2 - ctx->opts.aboxSlope, ymin, x2, ymid);
+ ctx->drw.line(&ctx->drw, x2, ymid, x2 - ctx->opts.aboxSlope, ymax);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ /* Restore the pen colour if needed */
+ if(lineColour)
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ }
+}
+
+
+/** Render text on an arc.
+ * Draw the text on some arc.
+ * \param m The Msc for which the text is being rendered.
+ * \param ismap If not \a NULL, write an ismap description here.
+ * \param outwidth Width of the output image.
+ * \param ymid Co-ordinate of the row on which the text should be aligned.
+ * \param startCol The column at which the arc being labelled starts.
+ * \param endCol The column at which the arc being labelled ends.
+ * \param arcLabelLineCount Count of lines of text in arcLabelLines.
+ * \param arcLabelLines Array of lines of text from 0 to arcLabelLineCount - 1.
+ * \param arcUrl The URL for rendering the label as a hyperlink. This
+ * maybe \a NULL if not required.
+ * \param arcId The text identifier for the arc.
+ * \param arcIdUrl The URL for rendering the test identifier as a hyperlink.
+ * This maybe \a NULL if not required.
+ * \param arcTextColour Colour for the arc text, or NULL to use default.
+ * \param arcTextColour Colour for the arc text backgroun, or NULL to use default.
+ * \param arcType The type of arc, used to control output semantics.
+ */
+static void arcText(Context *ctx,
+ Msc m,
+ FILE *ismap,
+ unsigned int outwidth,
+ unsigned int ymid,
+ int ygradient,
+ unsigned int startCol,
+ unsigned int endCol,
+ const unsigned int arcLabelLineCount,
+ char **arcLabelLines,
+ const char *arcUrl,
+ const char *arcId,
+ const char *arcIdUrl,
+ const char *arcTextColour,
+ const char *arcTextBgColour,
+ const MscArcType arcType)
+{
+ unsigned int l;
+ unsigned int y;
+
+ /* A single line of normal text is above the midline */
+ if(arcLabelLineCount == 1 && !isBoxArc(arcType) &&
+ arcType != MSC_ARC_DISCO && arcType != MSC_ARC_DIVIDER &&
+ arcType != MSC_ARC_SPACE)
+ {
+ y = ymid + (ygradient / 2) - ctx->drw.textHeight(&ctx->drw);
+ }
+ else /* Text is vertically centered on the midline */
+ {
+ int yoff = ygradient - (ctx->drw.textHeight(&ctx->drw) * arcLabelLineCount);
+ y = ymid + (yoff / 2);
+ }
+
+ for (l = 0; l < arcLabelLineCount; l++)
+ {
+ const char *lineLabel = arcLabelLines[l];
+ unsigned int width = ctx->drw.textWidth(&ctx->drw, lineLabel);
+ int x = ((startCol + endCol + 1) * ctx->opts.entitySpacing) / 2;
+
+ y += ctx->drw.textHeight(&ctx->drw);
+
+ if(startCol != endCol || isBoxArc(arcType))
+ {
+ /* Produce central aligned text */
+ x -= width / 2;
+ }
+ else if(startCol < (MscGetNumEntities(m) / 2))
+ {
+ /* Form text to the right */
+ x += ctx->opts.textHGapPre;
+ }
+ else
+ {
+ /* Form text to the left */
+ x -= width + ctx->opts.textHGapPost;
+ }
+
+ /* Clip against edges of image */
+ if(x + width > outwidth)
+ {
+ x = outwidth - width;
+ }
+
+ if(x < 0)
+ {
+ x = 0;
+ }
+
+ /* Check if a URL is associated */
+ if(arcUrl)
+ {
+ /* Default to blue */
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLUE);
+
+ /* Image map output */
+ ismapRect(ismap,
+ arcUrl,
+ x, y - ctx->drw.textHeight(&ctx->drw),
+ x + width, y);
+ }
+
+
+ /* Set to the explicit colours if directed */
+ if(arcTextColour != NULL)
+ {
+ ctx->drw.setPen(&ctx->drw, ADrawGetColour(arcTextColour));
+ }
+
+ if(arcTextBgColour != NULL)
+ {
+ ctx->drw.setBgPen(&ctx->drw, ADrawGetColour(arcTextBgColour));
+ }
+
+ /* Render text and restore pen */
+ ctx->drw.textR (&ctx->drw, x, y, lineLabel);
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ ctx->drw.setBgPen(&ctx->drw, ADRAW_COL_WHITE);
+
+ /* Render the Id of the arc, if specified and for the first line*/
+ if(arcId && l == 0)
+ {
+ unsigned int idwidth;
+ int idx, idy;
+
+ idy = y - ctx->drw.textHeight(&ctx->drw);
+ idx = x + width;
+
+ ctx->drw.setFontSize(&ctx->drw, ADRAW_FONT_TINY);
+
+ idwidth = ctx->drw.textWidth(&ctx->drw, arcId);
+ idy += (ctx->drw.textHeight(&ctx->drw) + 1) / 2;
+
+ if(arcIdUrl)
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLUE);
+
+ /* Image map output */
+ ismapRect(ismap,
+ arcIdUrl,
+ idx, idy - ctx->drw.textHeight(&ctx->drw),
+ idx + idwidth, idy);
+ }
+
+ /* Render text and restore pen and font */
+ ctx->drw.textR (&ctx->drw, idx, idy, arcId);
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ ctx->drw.setFontSize(&ctx->drw, ADRAW_FONT_SMALL);
+ }
+ }
+}
+
+
+/** Render the line and arrow head for some arc.
+ * This will draw the arc line and arrow head between two columns,
+ * noting that if the start and end column are the same, an arc is
+ * rendered.
+ * \param m The Msc for which the text is being rendered.
+ * \param ymin Top of row.
+ * \param ymax Bottom of row.
+ * \param ygradient The gradient of the arc which alters the y position a
+ * the ending column.
+ * \param startCol Starting column for the arc.
+ * \param endCol Column at which the arc terminates.
+ * \param hasArrows If true, draw arc arrows, otherwise omit them.
+ * \param hasBiArrows If true, has arrows in both directions.
+ * \param arcType The type of the arc, which dictates its rendered style.
+ */
+static void arcLine(Context *ctx,
+ Msc m,
+ unsigned int y,
+ unsigned int ygradient,
+ unsigned int startCol,
+ unsigned int endCol,
+ const char *arcLineCol,
+ Boolean hasArrows,
+ const int hasBiArrows,
+ const MscArcType arcType)
+{
+ const unsigned int sx = (startCol * ctx->opts.entitySpacing) +
+ (ctx->opts.entitySpacing / 2);
+ const unsigned int dx = (endCol * ctx->opts.entitySpacing) +
+ (ctx->opts.entitySpacing / 2);
+
+ /* Check if an explicit line colour is requested */
+ if(arcLineCol != NULL)
+ {
+ ctx->drw.setPen(&ctx->drw, ADrawGetColour(arcLineCol));
+ }
+
+ if(startCol != endCol)
+ {
+ /* Draw the line */
+ if(arcType == MSC_ARC_RETVAL)
+ {
+ ctx->drw.dottedLine(&ctx->drw, sx, y, dx, y + ygradient);
+ }
+ else if(arcType == MSC_ARC_DOUBLE)
+ {
+ ctx->drw.line(&ctx->drw, sx, y - 1, dx, y - 1 + ygradient);
+ ctx->drw.line(&ctx->drw, sx, y + 1, dx, y + 1 + ygradient);
+ }
+ else if(arcType == MSC_ARC_LOSS)
+ {
+ signed int span = dx - sx;
+ unsigned int mx = sx + (span / 4) * 3;
+
+ ctx->drw.line(&ctx->drw, sx, y, mx, y + ygradient);
+ hasArrows = 0;
+
+ ctx->drw.line(&ctx->drw, mx - 4, y + ygradient - 4, mx + 4, y + ygradient + 4);
+ ctx->drw.line(&ctx->drw, mx + 4, y + ygradient - 4, mx - 4, y + ygradient + 4);
+ }
+ else
+ {
+ ctx->drw.line(&ctx->drw, sx, y, dx, y + ygradient);
+ }
+
+ /* Now the arrow heads */
+ if(hasArrows)
+ {
+ if(startCol < endCol)
+ {
+ arrowR(ctx, dx, y + ygradient, arcType);
+ }
+ else
+ {
+ arrowL(ctx, dx, y + ygradient, arcType);
+ }
+
+ if(hasBiArrows)
+ {
+ if(startCol < endCol)
+ {
+ arrowL(ctx, sx, y + ygradient, arcType);
+ }
+ else
+ {
+ arrowR(ctx, sx, y + ygradient, arcType);
+ }
+ }
+ }
+ }
+ else if(startCol < (MscGetNumEntities(m) / 2))
+ {
+ /* Arc looping to the left */
+ if(arcType == MSC_ARC_RETVAL)
+ {
+ ctx->drw.dottedArc(&ctx->drw,
+ sx, y,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 90,
+ 270);
+ }
+ else if(arcType == MSC_ARC_DOUBLE)
+ {
+ ctx->drw.arc(&ctx->drw,
+ sx, y - 1,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 90,
+ 270);
+ ctx->drw.arc(&ctx->drw,
+ sx, y + 1,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 90,
+ 270);
+ }
+ else if(arcType == MSC_ARC_LOSS)
+ {
+ unsigned int px, py;
+
+ ctx->drw.arc(&ctx->drw,
+ sx, y - 1,
+ ctx->opts.entitySpacing - 8,
+ ctx->opts.loopArcHeight,
+ 180 - 45,
+ 270);
+
+ hasArrows = FALSE;
+
+ /* Get co-ordinates of the arc end-point */
+ ADrawComputeArcPoint(sx, y - 1, ctx->opts.entitySpacing - 8,
+ ctx->opts.loopArcHeight, 180 - 45,
+ &px, &py);
+
+ /* Draw a cross */
+ ctx->drw.line(&ctx->drw, px - 4, py - 4, px + 4, py + 4);
+ ctx->drw.line(&ctx->drw, px + 4, py - 4, px - 4, py + 4);
+ }
+ else
+ {
+ ctx->drw.arc(&ctx->drw,
+ sx, y,
+ ctx->opts.entitySpacing - 4,
+ ctx->opts.loopArcHeight,
+ 90,
+ 270);
+ }
+
+ if(hasArrows)
+ {
+ arrowR(ctx, dx, y + (ctx->opts.loopArcHeight / 2), arcType);
+ }
+ }
+ else
+ {
+ /* Arc looping to right */
+ if(arcType == MSC_ARC_RETVAL)
+ {
+ ctx->drw.dottedArc(&ctx->drw,
+ sx, y,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 270,
+ 90);
+ }
+ else if(arcType == MSC_ARC_DOUBLE)
+ {
+ ctx->drw.arc(&ctx->drw,
+ sx, y - 1,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 270,
+ 90);
+ ctx->drw.arc(&ctx->drw,
+ sx, y + 1,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 270,
+ 90);
+ }
+ else if(arcType == MSC_ARC_LOSS)
+ {
+ unsigned int px, py;
+
+ ctx->drw.arc(&ctx->drw,
+ sx, y - 1,
+ ctx->opts.entitySpacing - 8,
+ ctx->opts.loopArcHeight,
+ 270,
+ 45);
+
+ hasArrows = FALSE;
+
+ /* Get co-ordinates of the arc end-point */
+ ADrawComputeArcPoint(sx, y - 1, ctx->opts.entitySpacing - 8,
+ ctx->opts.loopArcHeight, 45,
+ &px, &py);
+
+ /* Draw a cross */
+ ctx->drw.line(&ctx->drw, px - 4, py - 4, px + 4, py + 4);
+ ctx->drw.line(&ctx->drw, px + 4, py - 4, px - 4, py + 4);
+ }
+ else
+ {
+ ctx->drw.arc(&ctx->drw,
+ sx, y,
+ ctx->opts.entitySpacing,
+ ctx->opts.loopArcHeight,
+ 270,
+ 90);
+ }
+
+ if(hasArrows)
+ {
+ arrowL(ctx, dx, y + (ctx->opts.loopArcHeight / 2), arcType);
+ }
+ }
+
+ /* Restore pen if needed */
+ if(arcLineCol != NULL)
+ {
+ ctx->drw.setPen(&ctx->drw, ADRAW_COL_BLACK);
+ }
+}
+
+
+
+/* Perform post-parsing validation of the MSC.
+ * This checks the passed MSC for various rules which can't easily be tested
+ * at parse time.
+ */
+static Boolean checkMsc(Msc m)
+{
+ /* Check all arc entites are known */
+ MscResetArcIterator(m);
+ do
+ {
+ const MscArcType arcType = MscGetCurrentArcType(m);
+
+ if (arcType != MSC_ARC_PARALLEL && arcType != MSC_ARC_DISCO &&
+ arcType != MSC_ARC_DIVIDER && arcType != MSC_ARC_SPACE)
+ {
+ const char *src = MscGetCurrentArcSource(m);
+ const char *dst = MscGetCurrentArcDest(m);
+ const int startCol = MscGetEntityIndex(m, src);
+ const int endCol = MscGetEntityIndex(m, dst);
+
+ /* Check the start column is valid */
+ if (startCol == -1)
+ {
+ fprintf(stderr, "Error detected at line %u: Unknown source entity '%s'.\n",
+ MscGetCurrentArcInputLine(m), src);
+ return FALSE;
+ }
+
+ if (endCol == -1 && !isBroadcastArc(dst))
+ {
+ fprintf(stderr, "Error detected at line %u: Unknown destination entity '%s'.\n",
+ MscGetCurrentArcInputLine(m), dst);
+ return FALSE;
+ }
+ }
+ }
+ while (MscNextArc(m));
+
+ return TRUE;
+}
+
+
+int mscgen_generate(const char *inputFile,
+ const char *outputFile,
+ mscgen_format_t format
+ )
+{
+ //printf("mscgen_generate(in=%s,out=%s,format=%d)\n",inputFile,outputFile,format);
+ ADrawOutputType outType;
+ ADrawColour *entColourRef = NULL;
+ const char *outImage = outputFile;
+ Msc m;
+ float f;
+ unsigned int w, h, row, col;
+ RowInfo *rowInfo = NULL;
+ Boolean addLines;
+ FILE *ismap = NULL;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const char *nullFile = "nul";
+#else
+ const char *nullFile = "/dev/null";
+#endif
+ Context ctx;
+ ctx.opts = gDefaultOpts;
+
+ switch (format)
+ {
+ case mscgen_format_png:
+ outType = ADRAW_FMT_PNG;
+ break;
+ case mscgen_format_eps:
+ outType = ADRAW_FMT_EPS;
+ break;
+ case mscgen_format_svg:
+ outType = ADRAW_FMT_SVG;
+ break;
+ case mscgen_format_pngmap:
+ outType = ADRAW_FMT_PNG;
+ outImage = nullFile;
+ break;
+ case mscgen_format_svgmap:
+ outType = ADRAW_FMT_SVG;
+ outImage = nullFile;
+ break;
+ }
+ /* open file */
+ FILE *in = fopen(inputFile, "r");
+ if (!in)
+ {
+ fprintf(stderr, "Failed to open input file '%s'\n", inputFile);
+ return MSCGEN_FILE_ERROR;
+ }
+ /* parse file */
+ m = MscParse(in);
+ fclose(in);
+ if (!m || !checkMsc(m))
+ {
+ fprintf(stderr, "Input format error for '%s'\n", inputFile);
+ return MSCGEN_INPUT_FORMAT_ERROR;
+ }
+
+ /* Check if an ismap file should also be generated */
+ if (format==mscgen_format_pngmap || format==mscgen_format_svgmap)
+ {
+ ismap = fopen(outputFile, "w");
+ if (!ismap)
+ {
+ fprintf(stderr, "Failed to open output file '%s': %s\n", outputFile, strerror(errno));
+ MscFree(m);
+ return MSCGEN_FILE_ERROR;
+ }
+ }
+
+ /* Open the drawing context with dummy dimensions */
+ if (!ADrawOpen(10, 10, nullFile, "", outType, &ctx.drw))
+ {
+ if (ismap)
+ {
+ fclose(ismap);
+ }
+ MscFree(m);
+ fprintf(stderr, "Failed to open temporary drawing context\n");
+ return MSCGEN_OUTPUT_CONTEXT_ERROR;
+ }
+
+ /* Now compute ideal canvas size, which may use text metrics */
+ if (MscGetOptAsFloat(m, MSC_OPT_WIDTH, &f))
+ {
+ ctx.opts.idealCanvasWidth = (unsigned int)f;
+ }
+ else if (MscGetOptAsFloat(m, MSC_OPT_HSCALE, &f))
+ {
+ ctx.opts.idealCanvasWidth *= (unsigned int)f;
+ }
+
+ /* Set the arc gradient if needed */
+ if (MscGetOptAsFloat(m, MSC_OPT_ARCGRADIENT, &f))
+ {
+ ctx.opts.arcGradient = (int)f;
+ ctx.opts.arcSpacing += ctx.opts.arcGradient;
+ }
+
+ /* Check if word wrapping on arcs other than boxes should be used */
+ MscGetOptAsBoolean(m, MSC_OPT_WORDWRAPARCS, &ctx.opts.wordWrapArcLabels);
+
+ /* Work out the entitySpacing */
+ if (ctx.opts.idealCanvasWidth / MscGetNumEntities(m) > ctx.opts.entitySpacing)
+ {
+ ctx.opts.entitySpacing = ctx.opts.idealCanvasWidth / MscGetNumEntities(m);
+ }
+
+ /* Work out the entityHeadGap */
+ MscResetEntityIterator(m);
+ for (col = 0; col < MscGetNumEntities(m); col++)
+ {
+ unsigned int lines = countLines(MscGetCurrentEntAttrib(m, MSC_ATTR_LABEL));
+ unsigned int gap;
+
+ /* Get the required gap */
+ gap = lines * ctx.drw.textHeight(&ctx.drw);
+ if (gap > ctx.opts.entityHeadGap)
+ {
+ ctx.opts.entityHeadGap = gap;
+ }
+
+ MscNextEntity(m);
+ }
+
+ //printf("opts: idealCanvasWidth=%d entitySpacing=%d entityHeadGap=%d "
+ // "arcSpacing=%d arcGradient=%d boxSpacing=%d boxInternalBorder=%d "
+ // "rboxArc=%d noteCorner=%d aboxSlope=%d wordWrapArcLabels=%d arrowWidth=%d "
+ // "arrowHeight=%d loopArcHeight=%d textHGapPre=%d textHGapPost=%d\n",
+ // ctx.opts.idealCanvasWidth,ctx.opts.entitySpacing,ctx.opts.entityHeadGap,
+ // ctx.opts.arcSpacing,ctx.opts.arcGradient,ctx.opts.boxSpacing,ctx.opts.boxInternalBorder,
+ // ctx.opts.rboxArc,ctx.opts.noteCorner,ctx.opts.aboxSlope,ctx.opts.wordWrapArcLabels,ctx.opts.arrowWidth,
+ // ctx.opts.arrowHeight,ctx.opts.loopArcHeight,ctx.opts.textHGapPre,ctx.opts.textHGapPost);
+
+ /* Work out the width and height of the canvas */
+ rowInfo = computeCanvasSize(&ctx, m, &w , &h);
+
+ /* Close the temporary output file */
+ ctx.drw.close(&ctx.drw);
+
+ //printf("opening canvas %d x %d for %s type=%d\n",w,h,outImage,outType);
+
+ /* Open the output */
+ if (!ADrawOpen(w, h, outImage, "", outType, &ctx.drw))
+ {
+ free(rowInfo);
+ if (ismap)
+ {
+ fclose(ismap);
+ }
+ MscFree(m);
+ return MSCGEN_OUTPUT_CONTEXT_ERROR;
+ }
+
+ /* Allocate storage for entity heading colours */
+ entColourRef = malloc_s(MscGetNumEntities(m) * sizeof(ADrawColour));
+
+ /* Draw the entity headings */
+ MscResetEntityIterator(m);
+ for (col = 0; col < MscGetNumEntities(m); col++)
+ {
+ unsigned int x = (ctx.opts.entitySpacing / 2) + (ctx.opts.entitySpacing * col);
+ const char *line;
+
+ /* Titles */
+ entityText(&ctx, ismap,
+ x,
+ ctx.opts.entityHeadGap - (ctx.drw.textHeight(&ctx.drw) / 2),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_LABEL),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_URL),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_ID),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_IDURL),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_TEXT_COLOUR),
+ MscGetCurrentEntAttrib(m, MSC_ATTR_TEXT_BGCOLOUR));
+
+ /* Get the colours */
+ line = MscGetCurrentEntAttrib(m, MSC_ATTR_LINE_COLOUR);
+ if (line != NULL)
+ {
+ entColourRef[col] = ADrawGetColour(line);
+ }
+ else
+ {
+ entColourRef[col] = ADRAW_COL_BLACK;
+ }
+
+ MscNextEntity(m);
+ }
+
+ /* Draw the arcs */
+ addLines = TRUE;
+ row = 0;
+
+ MscResetArcIterator(m);
+ do
+ {
+ const MscArcType arcType = MscGetCurrentArcType(m);
+ const char *arcUrl = MscGetCurrentArcAttrib(m, MSC_ATTR_URL);
+ const char *arcId = MscGetCurrentArcAttrib(m, MSC_ATTR_ID);
+ const char *arcIdUrl = MscGetCurrentArcAttrib(m, MSC_ATTR_IDURL);
+ const char *arcTextColour = MscGetCurrentArcAttrib(m, MSC_ATTR_TEXT_COLOUR);
+ const char *arcTextBgColour = MscGetCurrentArcAttrib(m, MSC_ATTR_TEXT_BGCOLOUR);
+ const char *arcLineColour = MscGetCurrentArcAttrib(m, MSC_ATTR_LINE_COLOUR);
+ const int arcGradient = isBoxArc(arcType) ? 0 : getArcGradient(&ctx, m, rowInfo, row);
+ const int arcHasArrows = MscGetCurrentArcAttrib(m, MSC_ATTR_NO_ARROWS) == NULL;
+ const int arcHasBiArrows = MscGetCurrentArcAttrib(m, MSC_ATTR_BI_ARROWS) != NULL;
+ char **arcLabelLines = NULL;
+ unsigned int arcLabelLineCount = 0;
+ int startCol = -1, endCol = -1;
+
+ if (arcType == MSC_ARC_PARALLEL)
+ {
+ addLines = FALSE;
+
+ /* Rewind the row */
+ assert(row > 0);
+ row--;
+ }
+ else
+ {
+ const unsigned int ymin = rowInfo[row].ymin;
+ const unsigned int ymid = rowInfo[row].arcliney;
+ const unsigned int ymax = rowInfo[row].ymax;
+
+#if 0
+ /* For debug, mark the row spacing */
+ ctx.drw.line(&ctx.drw, 0, ymin, 10, ymin);
+ ctx.drw.line(&ctx.drw, 0, ymid, 5, ymid);
+ ctx.drw.line(&ctx.drw, 0, ymax, 10, ymax);
+#endif
+ /* Get the entity indices */
+ if (arcType != MSC_ARC_DISCO && arcType != MSC_ARC_DIVIDER && arcType != MSC_ARC_SPACE)
+ {
+ startCol = MscGetEntityIndex(m, MscGetCurrentArcSource(m));
+ endCol = MscGetEntityIndex(m, MscGetCurrentArcDest(m));
+
+ /* Check that the start column is known and the end column is
+ * known, or that it's a broadcast arc
+ */
+ assert(startCol != -1);
+ assert(endCol != -1 || isBroadcastArc(MscGetCurrentArcDest(m)));
+
+ /* Check for entity colouring if not set explicity on the arc */
+ if (arcTextColour == NULL)
+ {
+ arcTextColour = MscGetEntAttrib(m, startCol, MSC_ATTR_ARC_TEXT_COLOUR);
+ }
+
+ if (arcTextBgColour == NULL)
+ {
+ arcTextBgColour = MscGetEntAttrib(m, startCol, MSC_ATTR_ARC_TEXT_BGCOLOUR);
+ }
+
+ if (arcLineColour == NULL)
+ {
+ arcLineColour = MscGetEntAttrib(m, startCol, MSC_ATTR_ARC_LINE_COLOUR);
+ }
+
+ }
+ else
+ {
+ /* Discontinuity or parallel arc spans whole chart */
+ startCol = 0;
+ endCol = MscGetNumEntities(m) - 1;
+ }
+
+ /* Work out how the label fits the gap between entities */
+ arcLabelLineCount = computeLabelLines(&ctx, m, arcType, &arcLabelLines,
+ MscGetCurrentArcAttrib(m, MSC_ATTR_LABEL),
+ startCol, endCol);
+
+ /* Check if this is a broadcast message */
+ if (isBroadcastArc(MscGetCurrentArcDest(m)))
+ {
+ unsigned int t;
+
+ /* Add in the entity lines */
+ if (addLines)
+ {
+ entityLines(&ctx, m, ymin, ymax + ctx.opts.arcSpacing, FALSE, entColourRef);
+ }
+
+ /* Draw arcs to each entity */
+ for (t = 0; t < MscGetNumEntities(m); t++)
+ {
+ if ((signed)t != startCol)
+ {
+ arcLine(&ctx, m, ymid, arcGradient, startCol,
+ t, arcLineColour, arcHasArrows,
+ arcHasBiArrows, arcType);
+ }
+ }
+
+ /* Fix up the start/end columns to span chart */
+ startCol = 0;
+ endCol = MscGetNumEntities(m) - 1;
+ }
+ else
+ {
+ /* Check if it is a box, discontinuity arc etc... */
+ if (isBoxArc(arcType))
+ {
+ if (addLines)
+ {
+ entityLines(&ctx, m, ymin, ymax + ctx.opts.arcSpacing, FALSE, entColourRef);
+ }
+ arcBox(&ctx, ymin, ymax, startCol, endCol, arcType, arcLineColour, arcTextBgColour);
+ }
+ else if (arcType == MSC_ARC_DISCO)
+ {
+ if (addLines)
+ {
+ entityLines(&ctx, m, ymin, ymax + ctx.opts.arcSpacing, TRUE /* dotted */, entColourRef);
+ }
+ }
+ else if (arcType == MSC_ARC_DIVIDER || arcType == MSC_ARC_SPACE)
+ {
+ if (addLines)
+ {
+ entityLines(&ctx, m, ymin, ymax + ctx.opts.arcSpacing, FALSE, entColourRef);
+ }
+
+ /* Dividers also have a horizontal line at the middle */
+ if (arcType == MSC_ARC_DIVIDER)
+ {
+ const unsigned int margin = ctx.opts.entitySpacing / 4;
+
+ if (arcLineColour != NULL)
+ {
+ ctx.drw.setPen(&ctx.drw, ADrawGetColour(arcLineColour));
+ }
+
+ /* Draw line through middle of text */
+ ctx.drw.dottedLine(&ctx.drw,
+ margin, ymid,
+ (MscGetNumEntities(m) * ctx.opts.entitySpacing) - margin, ymid);
+
+ if (arcLineColour != NULL)
+ {
+ ctx.drw.setPen(&ctx.drw, ADRAW_COL_BLACK);
+ }
+ }
+ }
+ else
+ {
+ if (addLines)
+ {
+ entityLines(&ctx, m, ymin, ymax + ctx.opts.arcSpacing, FALSE, entColourRef);
+ }
+ arcLine(&ctx, m, ymid, arcGradient, startCol, endCol, arcLineColour,
+ arcHasArrows, arcHasBiArrows, arcType);
+ }
+ }
+
+ /* All may have text */
+ if (arcLabelLineCount > 0)
+ {
+ arcText(&ctx, m, ismap, w, ymid, arcGradient,
+ startCol, endCol,
+ arcLabelLineCount, arcLabelLines,
+ arcUrl, arcId, arcIdUrl,
+ arcTextColour, arcTextBgColour, arcType);
+ }
+
+ freeLabelLines(arcLabelLineCount, arcLabelLines);
+
+ /* Advance the row */
+ row++;
+ addLines = TRUE;
+ }
+ } while (MscNextArc(m));
+
+ /* Skip arcs may require the entity lines to be extended */
+ entityLines(&ctx, m,
+ rowInfo[(MscGetNumArcs(m) - MscGetNumParallelArcs(m)) - 1].ymax,
+ h, FALSE, entColourRef);
+
+ if (ismap)
+ {
+ fclose(ismap);
+ }
+
+ free(entColourRef);
+ free(rowInfo);
+ MscFree(m);
+ /* Close the context */
+ ctx.drw.close(&ctx.drw);
+
+ return MSCGEN_OK;
+}
+
+
+const char *mscgen_error2str(int code)
+{
+ switch (code)
+ {
+ case MSCGEN_OK: return "OK";
+ case MSCGEN_FILE_ERROR: return "FILE ERROR";
+ case MSCGEN_INPUT_FORMAT_ERROR: return "INPUT FORMAT ERROR";
+ case MSCGEN_OUTPUT_CONTEXT_ERROR: return "OUTPUT CONTEXT ERROR";
+ default: return "UNKNOWN_ERROR";
+ }
+}
+
diff --git a/libmscgen/mscgen_api.h b/libmscgen/mscgen_api.h
new file mode 100644
index 0000000..43a1bf8
--- /dev/null
+++ b/libmscgen/mscgen_api.h
@@ -0,0 +1,41 @@
+#ifndef MSCGEN_API_H
+#define MSCGEN_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MSCGEN_OK ( 0)
+#define MSCGEN_FILE_ERROR (-1)
+#define MSCGEN_INPUT_FORMAT_ERROR (-2)
+#define MSCGEN_OUTPUT_CONTEXT_ERROR (-3)
+
+/** The supported image formats */
+typedef enum
+{
+ mscgen_format_png, /**< PNG bitmap image file */
+ mscgen_format_eps, /**< Encapsulated PostScript file */
+ mscgen_format_svg, /**< Scalable Vector Graphics file */
+ mscgen_format_pngmap, /**< Image map for a bitmap file */
+ mscgen_format_svgmap /**< Image map for a SVG file */
+} mscgen_format_t;
+
+/** generate an image file for a given .msc file.
+ * @param inputFile the name of the MSC file to process.
+ * @param outputFile the name of the image file to generate.
+ * @param format the format of the image file to generate.
+ * @return 0 on success, a non zero error code on failure.
+ */
+int mscgen_generate(const char *inputFile,
+ const char *outputFile,
+ mscgen_format_t format
+ );
+
+/** Translates the error code returned by mscgen_generate into a string */
+const char *mscgen_error2str(int code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MSCGEN_API_H
diff --git a/libmscgen/mscgen_bool.h b/libmscgen/mscgen_bool.h
new file mode 100644
index 0000000..e982d80
--- /dev/null
+++ b/libmscgen/mscgen_bool.h
@@ -0,0 +1,36 @@
+/***************************************************************************
+ *
+ * $Id: bool.h 115 2010-08-19 09:58:45Z Michael.McTernan $
+ *
+ * Boolean type for msclib.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ ***************************************************************************/
+
+#ifndef MSCGEN_BOOL_H
+#define MSCGEN_BOOL_H
+
+typedef enum
+{
+ FALSE = 0,
+ TRUE
+}
+Boolean;
+
+
+#endif /* MSCGEN_BOOL_H */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_config.h b/libmscgen/mscgen_config.h
new file mode 100644
index 0000000..194b965
--- /dev/null
+++ b/libmscgen/mscgen_config.h
@@ -0,0 +1,55 @@
+#ifndef MSCGEN_CONFIG_H
+#define MSCGEN_CONFIG_H
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define M_PI 3.14159265358979323846264338327950288
+#define strcasecmp _stricmp
+#define strdup _strdup
+#define fileno _fileno
+#define YY_NO_UNISTD_H 1
+#else
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+
+/* Name of package */
+#define PACKAGE "mscgen"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "Michael.McTernan.2001@cs.bris.ac.uk"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "mscgen"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "mscgen 0.20"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "mscgen"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.20"
+
+/* If set, remove PNG output support thereby removing libgd dependence. */
+//#define REMOVE_PNG_OUTPUT /**/
+
+/* Define to 1 if you have the ANSI C header files. */
+//#define STDC_HEADERS 1
+
+/* Use FreeType for rendering text in PNGs. */
+/* #undef USE_FREETYPE */
+
+/* Version number of package */
+#define VERSION "0.20"
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+#endif /* MSCGEN_CONFIG_H */
diff --git a/libmscgen/mscgen_gd_out.c b/libmscgen/mscgen_gd_out.c
new file mode 100644
index 0000000..263431e
--- /dev/null
+++ b/libmscgen/mscgen_gd_out.c
@@ -0,0 +1,606 @@
+/***************************************************************************
+ *
+ * $Id: gd_out.c 186 2011-03-01 21:18:19Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2010 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#include "mscgen_config.h"
+#ifndef REMOVE_PNG_OUTPUT
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include "gd.h"
+#ifndef USE_FREETYPE
+#include "gdfontt.h" /* Tiny font */
+#include "gdfonts.h" /* Small font */
+#endif
+#include "mscgen_adraw_int.h"
+#include "mscgen_safe.h"
+
+/***************************************************************************
+ * Manifest Constants
+ ***************************************************************************/
+
+#define MAX_COLOURS 128
+
+/***************************************************************************
+ * Local types
+ ***************************************************************************/
+
+typedef struct GdoContextTag
+{
+ gdImagePtr img;
+#ifdef USE_FREETYPE
+ double fontPoints;
+ const char *fontName;
+#else
+ gdFontPtr font;
+#endif
+
+ /** Array of colours and GD references. */
+ struct
+ {
+ int ref;
+ ADrawColour col;
+ }
+ colour[MAX_COLOURS];
+
+ /** Number of valid references in \a colourRef[]. */
+ int colourCount;
+
+ /** The current pen for GD. */
+ int pen;
+
+ /** Background colour for rendering text. */
+ int bgpen;
+
+ FILE *outFile;
+}
+GdoContext;
+
+/***************************************************************************
+ * Helper functions
+ ***************************************************************************/
+
+/** Swap a pair of values inplace.
+ */
+static void swap(unsigned int *a, unsigned int *b)
+{
+ unsigned int x;
+
+ x = *a;
+ *a = *b;
+ *b = x;
+}
+
+
+/** Get the context pointer from an ADraw structure.
+ */
+static GdoContext *getGdoCtx(struct ADrawTag *ctx)
+{
+ return (GdoContext *)ctx->internal;
+}
+
+
+/** Get the GD image pointer from an ADraw structure.
+ */
+static gdImagePtr getGdoImg(struct ADrawTag *ctx)
+{
+ return getGdoCtx(ctx)->img;
+}
+
+/** Get the current GD pen index from an ADraw structure.
+ */
+static int getGdoPen(struct ADrawTag *ctx)
+{
+ return getGdoCtx(ctx)->pen;
+}
+
+
+/** Given a colour value, convert to a gd colour reference.
+ * This searches the current pallette of colours for the passed colour and
+ * returns an existing reference if possible. Otherwise a new colour reference
+ * is allocated and returned.
+ */
+static int getColourRef(GdoContext *context, ADrawColour col)
+{
+ int t;
+
+ /* Check if the colour is already allocated */
+ for(t = 0; t < context->colourCount; t++)
+ {
+ if(context->colour[t].col == col)
+ {
+ return context->colour[t].ref;
+ }
+ }
+
+ /* Allocate a new colour if there is space */
+ if(t < MAX_COLOURS)
+ {
+ /* Store the colour and allocate a reference */
+ context->colour[t].col = col;
+ context->colour[t].ref = gdImageColorAllocate(context->img,
+ (col & 0xff0000) >> 16,
+ (col & 0x00ff00) >> 8,
+ (col & 0x0000ff) >> 0);
+ context->colourCount++;
+
+ /* Return the new colour reference */
+ return context->colour[t].ref;
+ }
+ else
+ {
+ /* Cannot allocate more colours, so return black by default */
+ return getColourRef(context, ADRAW_COL_BLACK);
+ }
+}
+
+
+/** Set the dashed style.
+ */
+static void setStyle(struct ADrawTag *ctx)
+{
+ GdoContext *context = getGdoCtx(ctx);
+ int style[4];
+
+ /* Create dash pattern */
+ style[0] = style[1] = context->pen;
+ style[2] = style[3] = getColourRef(context, ADRAW_COL_WHITE);
+
+ gdImageSetStyle(context->img, style, 4);
+}
+
+/***************************************************************************
+ * API Functions
+ ***************************************************************************/
+
+unsigned int gdoTextWidth(struct ADrawTag *ctx,
+ const char *string)
+{
+#ifndef USE_FREETYPE
+ const unsigned int l = strlen(string);
+
+ /* Remove 1 pixel since there is usually an uneven gap at
+ * the right of the last character for the fixed width
+ * font.
+ */
+ return l == 0 ? 0 : (getGdoCtx(ctx)->font->w * l) - 1;
+#else
+ GdoContext *context = getGdoCtx(ctx);
+ int rect[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ const char *r;
+
+ r = gdImageStringFT(NULL,
+ rect,
+ context->pen,
+ (char *)context->fontName,
+ context->fontPoints,
+ 0,
+ 0, 0,
+ (char *)string);
+ if(r)
+ {
+ fprintf(stderr, "Error: gdoTextWidth: %s (GDFONTPATH=%s)\n", r, mscgen_getenv_s("GDFONTPATH"));
+ exit(EXIT_FAILURE);
+ }
+
+ /* Remove 1 pixel since there is usually an uneven gap at
+ * the right of the last character for the fixed width
+ * font.
+ */
+ return rect[2] - 1;
+#endif
+}
+
+
+int gdoTextHeight(struct ADrawTag *ctx)
+{
+#ifndef USE_FREETYPE
+ return getGdoCtx(ctx)->font->h;
+#else
+ GdoContext *context = getGdoCtx(ctx);
+ int rect[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ const char *r;
+
+ r = gdImageStringFT(NULL,
+ rect,
+ context->pen,
+ (char *)context->fontName,
+ context->fontPoints,
+ 0,
+ 0, 0,
+ "gHELLOWt");
+ if(r)
+ {
+ fprintf(stderr, "Error: gdoTextHeight: %s (GDFONTPATH=%s)\n", r, mscgen_getenv_s("GDFONTPATH"));
+ exit(EXIT_FAILURE);
+ }
+
+ return (-rect[5]) + 1;
+#endif
+}
+
+
+void gdoLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ /* Range check since gdImageLine() takes signed values */
+ if(x1 <= INT_MAX && y1 <= INT_MAX && x2 <= INT_MAX && y2 <= INT_MAX)
+ {
+ /* Anti-aliasing fails if drawing 'backwards' for some octants */
+ if(x1 > x2 && abs((int)x1 - (int)x2) > abs((int)y1 - (int)y2))
+ {
+ swap(&x1, &x2);
+ swap(&y1, &y2);
+ }
+
+ gdImageSetAntiAliased(getGdoImg(ctx), getGdoPen(ctx));
+ gdImageLine(getGdoImg(ctx),
+ x1, y1, x2, y2, gdAntiAliased);
+ }
+}
+
+
+void gdoDottedLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ setStyle(ctx);
+
+ /* Range check since gdImageLine() takes signed values */
+ if(x1 <= INT_MAX && y1 <= INT_MAX && x2 <= INT_MAX && y2 <= INT_MAX)
+ {
+ gdImageLine(getGdoImg(ctx), x1, y1, x2, y2, gdStyled);
+ }
+}
+
+
+void gdoTextR(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ GdoContext *context = getGdoCtx(ctx);
+#ifdef USE_FREETYPE
+ int rect[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ const char *r;
+#endif
+ int textWidth;
+
+ textWidth = gdoTextWidth(ctx, string);
+
+ /* Range check since gdImageFilledRectangle() takes signed values */
+ if(x + textWidth <= INT_MAX && y <= INT_MAX)
+ {
+ gdImageFilledRectangle(getGdoImg(ctx),
+ x,
+ y - (gdoTextHeight(ctx) - 2),
+ x + textWidth,
+ y - 2,
+ context->bgpen);
+
+#ifdef USE_FREETYPE
+ r = gdImageStringFT(getGdoImg(ctx),
+ rect,
+ context->pen,
+ (char *)context->fontName,
+ context->fontPoints,
+ 0,
+ x, y - 2,
+ (char *)string);
+
+ if(r)
+ {
+ fprintf(stderr, "Error: gdoTextR: %s (GDFONTPATH=%s)\n", r, mscgen_getenv_s("GDFONTPATH"));
+ exit(EXIT_FAILURE);
+ }
+#else
+ gdImageString(getGdoImg(ctx),
+ getGdoCtx(ctx)->font,
+ x,
+ y - gdoTextHeight(ctx),
+ (unsigned char *)string,
+ getGdoPen(ctx));
+#endif
+ }
+
+}
+
+
+void gdoTextL(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ x -= gdoTextWidth(ctx, string);
+
+ /* Range check since gdImageFilledRectangle() takes signed values */
+ if(x <= INT_MAX && y <= INT_MAX)
+ {
+ gdoTextR(ctx, x, y, string);
+ }
+}
+
+void gdoTextC(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ gdoTextR(ctx, x - (gdoTextWidth(ctx, string) / 2), y, string);
+}
+
+void gdoFilledRectangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ gdPoint p[4];
+
+ /* Range check since gdPoint contains signed values */
+ if(x1 <= INT_MAX && y1 <= INT_MAX && x2 <= INT_MAX && y2 <= INT_MAX)
+ {
+ p[0].x = x1; p[0].y = y1;
+ p[1].x = x2; p[1].y = y1;
+ p[2].x = x2; p[2].y = y2;
+ p[3].x = x1; p[3].y = y2;
+
+
+ gdImageFilledPolygon(getGdoImg(ctx), p, 4, getGdoPen(ctx));
+ }
+}
+
+void gdoFilledTriangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2,
+ unsigned int x3,
+ unsigned int y3)
+{
+ gdPoint p[3];
+
+ /* Range check since gdPoint contains signed values */
+ if(x1 <= INT_MAX && y1 <= INT_MAX &&
+ x2 <= INT_MAX && y2 <= INT_MAX &&
+ x3 <= INT_MAX && y3 <= INT_MAX)
+ {
+ p[0].x = x1; p[0].y = y1;
+ p[1].x = x2; p[1].y = y2;
+ p[2].x = x3; p[2].y = y3;
+
+ gdImageSetAntiAliased(getGdoImg(ctx), getGdoPen(ctx));
+ gdImageFilledPolygon(getGdoImg(ctx), p, 3, gdAntiAliased);
+ }
+}
+
+
+void gdoFilledCircle(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ unsigned int r)
+{
+ gdImageSetAntiAliased(getGdoImg(ctx), getGdoPen(ctx));
+ gdImageFilledEllipse(getGdoImg(ctx), x, y, r * 2, r * 2, gdAntiAliased);
+}
+
+
+void gdoArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+
+ /* Range check since gdImageArc takes signed values */
+ if(cx <= INT_MAX && cy <= INT_MAX)
+ {
+ gdImageArc(getGdoImg(ctx), cx, cy, w, h, s, e, getGdoPen(ctx));
+ }
+}
+
+
+void gdoDottedArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+ /* Range check since gdImageArc takes signed values */
+ if(cx <= INT_MAX && cy <= INT_MAX)
+ {
+ setStyle(ctx);
+ gdImageArc(getGdoImg(ctx), cx, cy, w, h, s, e, gdStyled);
+ }
+}
+
+
+void gdoSetPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ GdoContext *context = getGdoCtx(ctx);;
+
+ context->pen = getColourRef(context, col);
+}
+
+
+void gdoSetBgPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ GdoContext *context = getGdoCtx(ctx);;
+
+ context->bgpen = getColourRef(context, col);
+}
+
+
+void gdoSetFontSize(struct ADrawTag *ctx,
+ ADrawFontSize size)
+{
+ switch(size)
+ {
+#ifdef USE_FREETYPE
+ case ADRAW_FONT_TINY:
+ getGdoCtx(ctx)->fontPoints = 9.0;
+ break;
+
+ case ADRAW_FONT_SMALL:
+ getGdoCtx(ctx)->fontPoints = 11.0;
+ break;
+#else
+ case ADRAW_FONT_TINY:
+ getGdoCtx(ctx)->font = gdFontGetTiny();
+ break;
+
+ case ADRAW_FONT_SMALL:
+ getGdoCtx(ctx)->font = gdFontGetSmall();
+ break;
+#endif
+ default:
+ assert(0);
+ }
+}
+
+
+Boolean gdoClose(struct ADrawTag *ctx)
+{
+ GdoContext *context = getGdoCtx(ctx);
+
+ /* Output the image to the disk file in PNG format. */
+ gdImagePng(getGdoImg(ctx), context->outFile);
+ if(context->outFile != stdout)
+ {
+ fclose(context->outFile);
+ }
+
+ /* Destroy the image in memory */
+ gdImageDestroy(context->img);
+
+ /* Free and destroy context */
+ free(context);
+ ctx->internal = NULL;
+
+ return TRUE;
+}
+
+
+
+Boolean GdoInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ const char *fontName UNUSED,
+ struct ADrawTag *outContext)
+{
+ GdoContext *context;
+
+ /* Range check the size */
+ if(w > INT_MAX || h > INT_MAX)
+ {
+ fprintf(stderr, "Warning: The output image size larger than can be supported for png; output\n"
+ " will be clipped.\n");
+ }
+
+ /* Clip image size to limits */
+ if(w > INT_MAX) w = INT_MAX;
+ if(h > INT_MAX) h = INT_MAX;
+
+ /* Create context */
+ context = outContext->internal = zalloc_s(sizeof(GdoContext));
+ if(context == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Open the output file */
+ if(strcmp(file, "-") == 0)
+ {
+ context->outFile = stdout;
+ }
+ else
+ {
+ context->outFile = fopen(file, "wb");
+ if(!context->outFile)
+ {
+ fprintf(stderr, "GdoInit: Failed to open output file '%s': %s\n", file, strerror(errno));
+ return FALSE;
+ }
+ }
+
+#ifdef USE_FREETYPE
+ /* Request that we use font config strings and store font name */
+ gdFTUseFontConfig(1);
+ context->fontName = fontName;
+
+ assert(fontName != NULL);
+#endif
+
+ /* Allocate the image */
+ context->img = gdImageCreateTrueColor(w, h);
+
+ /* Allocate first colour and clear background */
+ gdImageFilledRectangle(context->img,
+ 0, 0,
+ w, h,
+ getColourRef(context, ADRAW_COL_WHITE));
+
+ /* Set pen colour to black and background to white */
+ context->pen = getColourRef(context, ADRAW_COL_BLACK);
+ context->bgpen = getColourRef(context, ADRAW_COL_WHITE);
+
+ /* Get the default font size */
+ gdoSetFontSize(outContext, ADRAW_FONT_SMALL);
+
+ /* Now fill in the function pointers */
+ outContext->line = gdoLine;
+ outContext->dottedLine = gdoDottedLine;
+ outContext->textL = gdoTextL;
+ outContext->textC = gdoTextC;
+ outContext->textR = gdoTextR;
+ outContext->textWidth = gdoTextWidth;
+ outContext->textHeight = gdoTextHeight;
+ outContext->filledRectangle = gdoFilledRectangle;
+ outContext->filledTriangle = gdoFilledTriangle;
+ outContext->filledCircle = gdoFilledCircle;
+ outContext->arc = gdoArc;
+ outContext->dottedArc = gdoDottedArc;
+ outContext->setPen = gdoSetPen;
+ outContext->setBgPen = gdoSetBgPen;
+ outContext->setFontSize = gdoSetFontSize;
+ outContext->close = gdoClose;
+
+ return TRUE;
+}
+
+#endif /* REMOVE_PNG_OUTPUT */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_language.h b/libmscgen/mscgen_language.h
new file mode 100644
index 0000000..4f401a6
--- /dev/null
+++ b/libmscgen/mscgen_language.h
@@ -0,0 +1,186 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ TOK_STRING = 258,
+ TOK_QSTRING = 259,
+ TOK_EQUAL = 260,
+ TOK_COMMA = 261,
+ TOK_SEMICOLON = 262,
+ TOK_OCBRACKET = 263,
+ TOK_CCBRACKET = 264,
+ TOK_OSBRACKET = 265,
+ TOK_CSBRACKET = 266,
+ TOK_MSC = 267,
+ TOK_ATTR_LABEL = 268,
+ TOK_ATTR_URL = 269,
+ TOK_ATTR_ID = 270,
+ TOK_ATTR_IDURL = 271,
+ TOK_ATTR_LINE_COLOUR = 272,
+ TOK_ATTR_TEXT_COLOUR = 273,
+ TOK_ATTR_TEXT_BGCOLOUR = 274,
+ TOK_ATTR_ARC_LINE_COLOUR = 275,
+ TOK_ATTR_ARC_TEXT_COLOUR = 276,
+ TOK_ATTR_ARC_TEXT_BGCOLOUR = 277,
+ TOK_REL_LOSS_TO = 278,
+ TOK_REL_LOSS_FROM = 279,
+ TOK_REL_SIG_BI = 280,
+ TOK_REL_SIG_TO = 281,
+ TOK_REL_SIG_FROM = 282,
+ TOK_REL_METHOD_BI = 283,
+ TOK_REL_METHOD_TO = 284,
+ TOK_REL_METHOD_FROM = 285,
+ TOK_REL_RETVAL_BI = 286,
+ TOK_REL_RETVAL_TO = 287,
+ TOK_REL_RETVAL_FROM = 288,
+ TOK_REL_DOUBLE_BI = 289,
+ TOK_REL_DOUBLE_TO = 290,
+ TOK_REL_DOUBLE_FROM = 291,
+ TOK_REL_CALLBACK_BI = 292,
+ TOK_REL_CALLBACK_TO = 293,
+ TOK_REL_CALLBACK_FROM = 294,
+ TOK_REL_BOX = 295,
+ TOK_REL_ABOX = 296,
+ TOK_REL_RBOX = 297,
+ TOK_REL_NOTE = 298,
+ TOK_SPECIAL_ARC = 299,
+ TOK_OPT_HSCALE = 300,
+ TOK_OPT_WIDTH = 301,
+ TOK_OPT_ARCGRADIENT = 302,
+ TOK_OPT_WORDWRAPARCS = 303,
+ TOK_ASTERISK = 304,
+ TOK_UNKNOWN = 305,
+ TOK_REL_SIG = 306,
+ TOK_REL_METHOD = 307,
+ TOK_REL_RETVAL = 308,
+ TOK_REL_DOUBLE = 309,
+ TOK_ATTR_ARC_SKIP = 310
+ };
+#endif
+/* Tokens. */
+#define TOK_STRING 258
+#define TOK_QSTRING 259
+#define TOK_EQUAL 260
+#define TOK_COMMA 261
+#define TOK_SEMICOLON 262
+#define TOK_OCBRACKET 263
+#define TOK_CCBRACKET 264
+#define TOK_OSBRACKET 265
+#define TOK_CSBRACKET 266
+#define TOK_MSC 267
+#define TOK_ATTR_LABEL 268
+#define TOK_ATTR_URL 269
+#define TOK_ATTR_ID 270
+#define TOK_ATTR_IDURL 271
+#define TOK_ATTR_LINE_COLOUR 272
+#define TOK_ATTR_TEXT_COLOUR 273
+#define TOK_ATTR_TEXT_BGCOLOUR 274
+#define TOK_ATTR_ARC_LINE_COLOUR 275
+#define TOK_ATTR_ARC_TEXT_COLOUR 276
+#define TOK_ATTR_ARC_TEXT_BGCOLOUR 277
+#define TOK_REL_LOSS_TO 278
+#define TOK_REL_LOSS_FROM 279
+#define TOK_REL_SIG_BI 280
+#define TOK_REL_SIG_TO 281
+#define TOK_REL_SIG_FROM 282
+#define TOK_REL_METHOD_BI 283
+#define TOK_REL_METHOD_TO 284
+#define TOK_REL_METHOD_FROM 285
+#define TOK_REL_RETVAL_BI 286
+#define TOK_REL_RETVAL_TO 287
+#define TOK_REL_RETVAL_FROM 288
+#define TOK_REL_DOUBLE_BI 289
+#define TOK_REL_DOUBLE_TO 290
+#define TOK_REL_DOUBLE_FROM 291
+#define TOK_REL_CALLBACK_BI 292
+#define TOK_REL_CALLBACK_TO 293
+#define TOK_REL_CALLBACK_FROM 294
+#define TOK_REL_BOX 295
+#define TOK_REL_ABOX 296
+#define TOK_REL_RBOX 297
+#define TOK_REL_NOTE 298
+#define TOK_SPECIAL_ARC 299
+#define TOK_OPT_HSCALE 300
+#define TOK_OPT_WIDTH 301
+#define TOK_OPT_ARCGRADIENT 302
+#define TOK_OPT_WORDWRAPARCS 303
+#define TOK_ASTERISK 304
+#define TOK_UNKNOWN 305
+#define TOK_REL_SIG 306
+#define TOK_REL_METHOD 307
+#define TOK_REL_RETVAL 308
+#define TOK_REL_DOUBLE 309
+#define TOK_ATTR_ARC_SKIP 310
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c */
+#line 248 "language.y"
+
+ char *string;
+ Msc msc;
+ MscOpt opt;
+ MscOptType optType;
+ MscArc arc;
+ MscArcList arclist;
+ MscArcType arctype;
+ MscEntity entity;
+ MscEntityList entitylist;
+ MscAttrib attrib;
+ MscAttribType attribType;
+
+
+
+/* Line 1676 of yacc.c */
+#line 178 "language.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+extern YYSTYPE yylval;
+
+
diff --git a/libmscgen/mscgen_language.y b/libmscgen/mscgen_language.y
new file mode 100644
index 0000000..0c0ab50
--- /dev/null
+++ b/libmscgen/mscgen_language.y
@@ -0,0 +1,430 @@
+%{
+/***************************************************************************
+ *
+ * $Id: language.y 175 2011-02-06 21:07:43Z Michael.McTernan $
+ *
+ * Grammar and parser for the mscgen language.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This file is part of msclib.
+ *
+ * Msc is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * Msclib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Foobar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mscgen_lexer.h"
+#include "mscgen_safe.h"
+#include "mscgen_msc.h"
+
+/* Lexer prototypes to prevent compiler warnings */
+int yylex(void);
+int yylex_destroy(void);
+
+/* Use verbose error reporting such that the expected token names are dumped */
+#define YYERROR_VERBOSE
+
+/* Name of parameter that is passed to yyparse() */
+#define YYPARSE_PARAM yyparse_result
+
+#define YYMALLOC malloc_s
+
+/* yyerror
+ * Error handling function. The TOK_XXX names are substituted for more
+ * understandable values that make more sense to the user.
+ */
+void yyerror(void *unused, const char *str)
+{
+ static const char *tokNames[] = { "TOK_OCBRACKET", "TOK_CCBRACKET",
+ "TOK_OSBRACKET", "TOK_CSBRACKET",
+ "TOK_REL_DOUBLE_TO", "TOK_REL_DOUBLE_FROM",
+ "TOK_REL_SIG_TO", "TOK_REL_SIG_FROM",
+ "TOK_REL_METHOD_TO", "TOK_REL_METHOD_FROM",
+ "TOK_REL_RETVAL_TO", "TOK_REL_RETVAL_FROM",
+ "TOK_REL_CALLBACK_TO", "TOK_REL_CALLBACK_FROM",
+ "TOK_REL_SIG", "TOK_REL_METHOD",
+ "TOK_REL_RETVAL", "TOK_REL_DOUBLE",
+ "TOK_EQUAL", "TOK_COMMA",
+ "TOK_SEMICOLON", "TOK_MSC",
+ "TOK_ATTR_LABEL", "TOK_ATTR_URL",
+ "TOK_ATTR_IDURL", "TOK_ATTR_ID",
+ "TOK_ATTR_LINE_COLOUR", "TOK_ATTR_TEXT_COLOUR",
+ "TOK_SPECIAL_ARC", "TOK_UNKNOWN",
+ "TOK_STRING", "TOK_QSTRING",
+ "TOK_OPT_HSCALE", "TOK_ASTERISK",
+ "TOK_OPT_WIDTH", "TOK_ARC_BOX",
+ "TOK_ARC_ABOX", "TOK_ARC_RBOX",
+ "TOK_ATTR_TEXT_BGCOLOUR", "TOK_ATTR_ARC_TEXT_BGCOLOUR",
+ "TOK_REL_LOSS_TO", "TOK_REL_LOSS_FROM",
+ "TOK_OPT_ARCGRADIENT", "TOK_ATTR_ARC_SKIP",
+ "TOK_OPT_WORDWRAPARCS", "TOK_REL_NOTE" };
+
+ static const char *tokRepl[] = { "'{'", "'}'",
+ "'['", "']'",
+ "':>'", "'<:'",
+ "'->'", "'<-'",
+ "'=>'", "'<='",
+ "'>>'", "'<<'",
+ "'=>>'", "'<<='",
+ "'--'", "'=='",
+ "'..'", "'::'",
+ "'='", "','",
+ "';'", "'msc'",
+ "'label'", "'url'",
+ "'idurl'", "'id'",
+ "'linecolour'", "'textcolour'",
+ "'...', '---'", "characters",
+ "'string'", "'quoted string'",
+ "'hscale'", "'*'",
+ "'width'", "'box'",
+ "'abox'", "'rbox'",
+ "'textbgcolour'", "'arctextbgcolor'",
+ "'-x'", "'x-'",
+ "'arcgradient'", "'arcskip'",
+ "'wordwraparcs'", "'note'" };
+
+ static const int tokArrayLen = sizeof(tokNames) / sizeof(char *);
+
+ char *s, *line;
+ int t;
+
+ /* Print standard message part */
+ fprintf(stderr, "Error detected at line %lu: ", lex_getlinenum());
+
+ /* Search for TOK */
+ s = (char *)strstr(str, "TOK_");
+ while(s != NULL)
+ {
+ int found = 0;
+
+ /* Print out message until start of the token is found */
+ while(str < s)
+ {
+ fprintf(stderr, "%c", *str);
+ str++;
+ }
+
+ /* Look for the token name */
+ for(t = 0; t < tokArrayLen && !found; t++)
+ {
+ if(strncmp(tokNames[t], str, strlen(tokNames[t])) == 0)
+ {
+ /* Dump the replacement string */
+ fprintf(stderr, "%s", tokRepl[t]);
+
+ /* Skip the token name */
+ str += strlen(tokNames[t]);
+
+ /* Exit the loop */
+ found = 1;
+ }
+ }
+
+ /* Check if a replacement was found */
+ if(!found)
+ {
+ /* Dump the next char and skip it so that TOK doesn't match again */
+ fprintf(stderr, "%c", *str);
+ str++;
+ }
+
+ s = (char *)strstr(str, "TOK_");
+ }
+
+ fprintf(stderr, "%s.\n", str);
+
+ line = lex_getline();
+ if(line != NULL)
+ {
+ fprintf(stderr, "> %s\n", line);
+
+ /* If the input line contains a 'lost arc', print a helpful note since
+ * without whitespace, this can confuse the lexer.
+ */
+ if(strstr(line, "x-") != NULL)
+ {
+ fprintf(stderr, "\nNote: This input line contains 'x-' which has special meaning as a \n"
+ " 'lost message' arc, but may not have been recognised as such if it\n"
+ " is preceded by other letters or numbers. Please use double-quoted\n"
+ " strings for tokens before 'x-', or insert a preceding whitespace if\n"
+ " this is what you intend.\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr, ".\n");
+ }
+}
+
+int yywrap()
+{
+ return 1;
+}
+
+
+char *removeEscapes(char *in)
+{
+ const uint16_t l = strlen(in);
+ char *r = (char *)malloc_s(l + 1);
+ uint16_t t, u;
+
+ for(t = u = 0; t < l; t++)
+ {
+ r[u] = in[t];
+ if(in[t] != '\\' || in[t + 1] != '\"')
+ {
+ u++;
+ }
+ }
+
+ r[u] = '\0';
+
+ free(in);
+
+ return r;
+}
+
+extern FILE *yyin;
+extern int yyparse (void *YYPARSE_PARAM);
+
+
+Msc MscParse(FILE *in)
+{
+ Msc m;
+
+ yyin = in;
+
+ /* Parse, and check that no errors are found */
+ if(yyparse((void *)&m) != 0)
+ {
+ m = NULL;
+ }
+
+ lex_destroy();
+ yylex_destroy();
+
+ return m;
+}
+
+
+%}
+
+%parse-param {void *YYPARSE_PARAM}
+
+%token TOK_STRING TOK_QSTRING TOK_EQUAL TOK_COMMA TOK_SEMICOLON TOK_OCBRACKET TOK_CCBRACKET
+ TOK_OSBRACKET TOK_CSBRACKET TOK_MSC
+ TOK_ATTR_LABEL TOK_ATTR_URL TOK_ATTR_ID TOK_ATTR_IDURL
+ TOK_ATTR_LINE_COLOUR TOK_ATTR_TEXT_COLOUR TOK_ATTR_TEXT_BGCOLOUR
+ TOK_ATTR_ARC_LINE_COLOUR TOK_ATTR_ARC_TEXT_COLOUR TOK_ATTR_ARC_TEXT_BGCOLOUR
+ TOK_REL_LOSS_TO TOK_REL_LOSS_FROM
+ TOK_REL_SIG_BI TOK_REL_SIG_TO TOK_REL_SIG_FROM
+ TOK_REL_METHOD_BI TOK_REL_METHOD_TO TOK_REL_METHOD_FROM
+ TOK_REL_RETVAL_BI TOK_REL_RETVAL_TO TOK_REL_RETVAL_FROM
+ TOK_REL_DOUBLE_BI TOK_REL_DOUBLE_TO TOK_REL_DOUBLE_FROM
+ TOK_REL_CALLBACK_BI TOK_REL_CALLBACK_TO TOK_REL_CALLBACK_FROM
+ TOK_REL_BOX TOK_REL_ABOX
+ TOK_REL_RBOX TOK_REL_NOTE
+ TOK_SPECIAL_ARC TOK_OPT_HSCALE
+ TOK_OPT_WIDTH TOK_OPT_ARCGRADIENT
+ TOK_OPT_WORDWRAPARCS
+ TOK_ASTERISK TOK_UNKNOWN
+ TOK_REL_SIG TOK_REL_METHOD TOK_REL_RETVAL TOK_REL_DOUBLE
+ TOK_ATTR_ARC_SKIP
+
+%union
+{
+ char *string;
+ Msc msc;
+ MscOpt opt;
+ MscOptType optType;
+ MscArc arc;
+ MscArcList arclist;
+ MscArcType arctype;
+ MscEntity entity;
+ MscEntityList entitylist;
+ MscAttrib attrib;
+ MscAttribType attribType;
+};
+
+%type <msc> msc
+%type <opt> optlist opt
+%type <optType> optval TOK_OPT_HSCALE TOK_OPT_WIDTH TOK_OPT_ARCGRADIENT TOK_OPT_WORDWRAPARCS
+%type <arc> arc arcrel
+%type <arclist> arclist
+%type <entity> entity
+%type <entitylist> entitylist
+%type <arctype> relation_box relation_line relation_bi relation_to relation_from
+ TOK_REL_SIG_BI TOK_REL_METHOD_BI TOK_REL_RETVAL_BI TOK_REL_CALLBACK_BI
+ TOK_REL_SIG_TO TOK_REL_METHOD_TO TOK_REL_RETVAL_TO TOK_REL_CALLBACK_TO TOK_REL_DOUBLE_BI
+ TOK_REL_SIG_FROM TOK_REL_METHOD_FROM TOK_REL_RETVAL_FROM TOK_REL_CALLBACK_FROM
+ TOK_REL_DOUBLE_TO TOK_REL_DOUBLE_FROM
+ TOK_REL_LOSS_TO TOK_REL_LOSS_FROM
+ TOK_SPECIAL_ARC TOK_REL_BOX TOK_REL_ABOX TOK_REL_RBOX TOK_REL_NOTE
+ TOK_REL_SIG TOK_REL_METHOD TOK_REL_RETVAL TOK_REL_DOUBLE
+%type <attrib> attrlist attr
+%type <attribType> attrval
+ TOK_ATTR_LABEL TOK_ATTR_URL TOK_ATTR_ID TOK_ATTR_IDURL
+ TOK_ATTR_LINE_COLOUR TOK_ATTR_TEXT_COLOUR TOK_ATTR_TEXT_BGCOLOUR
+ TOK_ATTR_ARC_LINE_COLOUR TOK_ATTR_ARC_TEXT_COLOUR TOK_ATTR_ARC_TEXT_BGCOLOUR
+ TOK_ATTR_ARC_SKIP
+%type <string> string TOK_STRING TOK_QSTRING
+
+
+%%
+msc: TOK_MSC TOK_OCBRACKET optlist TOK_SEMICOLON entitylist TOK_SEMICOLON arclist TOK_SEMICOLON TOK_CCBRACKET
+{
+ $$ = MscAlloc($3, $5, $7);
+ *(Msc *)yyparse_result = $$;
+
+}
+ | TOK_MSC TOK_OCBRACKET entitylist TOK_SEMICOLON arclist TOK_SEMICOLON TOK_CCBRACKET
+{
+ $$ = MscAlloc(NULL, $3, $5);
+ *(Msc *)yyparse_result = $$;
+
+};
+
+optlist: opt
+ | optlist TOK_COMMA opt
+{
+ $$ = MscLinkOpt($1, $3);
+};
+
+opt: optval TOK_EQUAL string
+{
+ $$ = MscAllocOpt($1, $3);
+};
+
+optval: TOK_OPT_HSCALE | TOK_OPT_WIDTH | TOK_OPT_ARCGRADIENT | TOK_OPT_WORDWRAPARCS;
+
+entitylist: entity
+{
+ $$ = MscLinkEntity(NULL, $1); /* Create new list */
+}
+ | entitylist TOK_COMMA entity
+{
+ $$ = MscLinkEntity($1, $3); /* Add to existing list */
+};
+
+
+
+entity: string
+{
+ $$ = MscAllocEntity($1);
+}
+ | entity TOK_OSBRACKET attrlist TOK_CSBRACKET
+{
+ MscEntityLinkAttrib($1, $3);
+}
+;
+
+arclist: arc
+{
+ $$ = MscLinkArc(NULL, $1); /* Create new list */
+}
+ | arclist TOK_SEMICOLON arc
+{
+ $$ = MscLinkArc($1, $3); /* Add to existing list */
+}
+ | arclist TOK_COMMA arc
+{
+ /* Add a special 'parallel' arc */
+ $$ = MscLinkArc(MscLinkArc($1, MscAllocArc(NULL, NULL, MSC_ARC_PARALLEL, lex_getlinenum())), $3);
+};
+;
+
+
+
+arc: arcrel TOK_OSBRACKET attrlist TOK_CSBRACKET
+{
+ MscArcLinkAttrib($1, $3);
+}
+ | arcrel;
+
+arcrel: TOK_SPECIAL_ARC
+{
+ $$ = MscAllocArc(NULL, NULL, $1, lex_getlinenum());
+}
+ | string relation_box string
+{
+ $$ = MscAllocArc($1, $3, $2, lex_getlinenum());
+}
+ | string relation_bi string
+{
+ MscArc arc = MscAllocArc($1, $3, $2, lex_getlinenum());
+ MscArcLinkAttrib(arc, MscAllocAttrib(MSC_ATTR_BI_ARROWS, strdup_s("true")));
+ $$ = arc;
+}
+ | string relation_to string
+{
+ $$ = MscAllocArc($1, $3, $2, lex_getlinenum());
+}
+ | string relation_line string
+{
+ MscArc arc = MscAllocArc($1, $3, $2, lex_getlinenum());
+ MscArcLinkAttrib(arc, MscAllocAttrib(MSC_ATTR_NO_ARROWS, strdup_s("true")));
+ $$ = arc;
+}
+ | string relation_from string
+{
+ $$ = MscAllocArc($3, $1, $2, lex_getlinenum());
+}
+ | string relation_to TOK_ASTERISK
+{
+ $$ = MscAllocArc($1, strdup_s("*"), $2, lex_getlinenum());
+}
+ | TOK_ASTERISK relation_from string
+{
+ $$ = MscAllocArc($3, strdup_s("*"), $2, lex_getlinenum());
+};
+
+relation_box: TOK_REL_BOX | TOK_REL_ABOX | TOK_REL_RBOX | TOK_REL_NOTE;
+relation_line: TOK_REL_SIG | TOK_REL_METHOD | TOK_REL_RETVAL | TOK_REL_DOUBLE;
+relation_bi: TOK_REL_SIG_BI | TOK_REL_METHOD_BI | TOK_REL_RETVAL_BI | TOK_REL_CALLBACK_BI | TOK_REL_DOUBLE_BI;
+relation_to: TOK_REL_SIG_TO | TOK_REL_METHOD_TO | TOK_REL_RETVAL_TO | TOK_REL_CALLBACK_TO | TOK_REL_DOUBLE_TO | TOK_REL_LOSS_TO;
+relation_from: TOK_REL_SIG_FROM | TOK_REL_METHOD_FROM | TOK_REL_RETVAL_FROM | TOK_REL_CALLBACK_FROM | TOK_REL_DOUBLE_FROM | TOK_REL_LOSS_FROM;
+
+attrlist: attr
+ | attrlist TOK_COMMA attr
+{
+ $$ = MscLinkAttrib($1, $3);
+};
+
+attr: attrval TOK_EQUAL string
+{
+ $$ = MscAllocAttrib($1, $3);
+};
+
+attrval: TOK_ATTR_LABEL | TOK_ATTR_URL | TOK_ATTR_ID | TOK_ATTR_IDURL |
+ TOK_ATTR_LINE_COLOUR | TOK_ATTR_TEXT_COLOUR | TOK_ATTR_TEXT_BGCOLOUR |
+ TOK_ATTR_ARC_LINE_COLOUR | TOK_ATTR_ARC_TEXT_COLOUR | TOK_ATTR_ARC_TEXT_BGCOLOUR |
+ TOK_ATTR_ARC_SKIP;
+
+
+string: TOK_QSTRING
+{
+ $$ = removeEscapes($1);
+}
+ | TOK_STRING
+{
+ $$ = $1;
+};
+%%
+
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_lexer.h b/libmscgen/mscgen_lexer.h
new file mode 100644
index 0000000..0cbb21f
--- /dev/null
+++ b/libmscgen/mscgen_lexer.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ *
+ * $Id: lexer.h 152 2010-10-10 14:17:37Z Michael.McTernan $
+ *
+ * Extra lexer/scanner API functions.
+ * Copyright (C) 2010 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ ***************************************************************************/
+
+#ifndef MSCGEN_LEXER_H
+#define MSCGEN_LEXER_H
+
+/*****************************************************************************
+ * Header Files
+ *****************************************************************************/
+
+#include "mscgen_bool.h"
+
+/*****************************************************************************
+ * Preprocessor Macros & Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Typedefs
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Variable Declarations
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Function Declarations
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+Boolean lex_getutf8(void);
+#ifdef __cplusplus
+}
+#endif
+
+unsigned long lex_getlinenum(void);
+char *lex_getline(void);
+void lex_destroy(void);
+
+#endif /* MSCGEN_LEXER_H */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_lexer.l b/libmscgen/mscgen_lexer.l
new file mode 100644
index 0000000..29d6aea
--- /dev/null
+++ b/libmscgen/mscgen_lexer.l
@@ -0,0 +1,236 @@
+%{
+/***************************************************************************
+ *
+ * $Id: lexer.l 184 2011-02-28 21:38:28Z Michael.McTernan $
+ *
+ * Mscgen language lexer definition.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This file is part of msclib.
+ *
+ * Msc is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * Msclib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with msclib; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "mscgen_config.h"
+#include "mscgen_msc.h"
+#include "mscgen_bool.h"
+#include "mscgen_safe.h"
+#include "mscgen_lexer.h"
+#include "mscgen_language.h" /* Token definitions from Yacc/Bison */
+/* Counter for error reporting */
+static unsigned long lex_linenum = 1;
+static char *lex_line = NULL;
+static Boolean lex_utf8 = FALSE;
+
+/* Local function prototypes */
+static void newline(const char *text, unsigned int n);
+static char *trimQstring(char *s);
+
+%}
+
+/* Not used, so prevent compiler warning */
+%option never-interactive
+%option noinput
+%option noyywrap
+
+%x IN_COMMENT BODY
+%%
+
+<INITIAL>{
+\xef\xbb\xbf lex_utf8 = TRUE; BEGIN(BODY);
+(\r\n).* newline(yytext, 2); BEGIN(BODY);
+(\r|\n).* newline(yytext, 1); BEGIN(BODY);
+. unput(yytext[0]); BEGIN(BODY);
+}
+
+<IN_COMMENT>{
+"*/" BEGIN(BODY);
+[^*\n]+
+"*"
+(\r\n).* newline(yytext, 2);
+(\r|\n).* newline(yytext, 1);
+}
+
+<BODY>{
+
+"/*" BEGIN(IN_COMMENT);
+
+(\r\n).* newline(yytext, 2);
+(\r|\n).* newline(yytext, 1);
+
+#.*$ /* Ignore lines after '#' */
+\/\/.*$ /* Ignore lines after '//' */
+
+msc return TOK_MSC;
+HSCALE|hscale yylval.optType = MSC_OPT_HSCALE; return TOK_OPT_HSCALE;
+WIDTH|width yylval.optType = MSC_OPT_WIDTH; return TOK_OPT_WIDTH;
+ARCGRADIENT|arcgradient yylval.optType = MSC_OPT_ARCGRADIENT; return TOK_OPT_ARCGRADIENT;
+WORDWRAPARCS|wordwraparcs yylval.optType = MSC_OPT_WORDWRAPARCS; return TOK_OPT_WORDWRAPARCS;
+URL|url yylval.attribType = MSC_ATTR_URL; return TOK_ATTR_URL;
+LABEL|label yylval.attribType = MSC_ATTR_LABEL; return TOK_ATTR_LABEL;
+IDURL|idurl yylval.attribType = MSC_ATTR_IDURL; return TOK_ATTR_IDURL;
+ID|id yylval.attribType = MSC_ATTR_ID; return TOK_ATTR_ID;
+LINECOLO(U?)R|linecolo(u?)r yylval.attribType = MSC_ATTR_LINE_COLOUR; return TOK_ATTR_LINE_COLOUR;
+TEXTCOLO(U?)R|textcolo(u?)r yylval.attribType = MSC_ATTR_TEXT_COLOUR; return TOK_ATTR_TEXT_COLOUR;
+TEXTBGCOLO(U?)R|textbgcolo(u?)r yylval.attribType = MSC_ATTR_TEXT_BGCOLOUR; return TOK_ATTR_TEXT_BGCOLOUR;
+ARCLINECOLO(U?)R|arclinecolo(u?)r yylval.attribType = MSC_ATTR_ARC_LINE_COLOUR; return TOK_ATTR_ARC_LINE_COLOUR;
+ARCTEXTCOLO(U?)R|arctextcolo(u?)r yylval.attribType = MSC_ATTR_ARC_TEXT_COLOUR; return TOK_ATTR_ARC_TEXT_COLOUR;
+ARCTEXTBGCOLO(U?)R|arctextbgcolo(u?)r yylval.attribType = MSC_ATTR_ARC_TEXT_BGCOLOUR; return TOK_ATTR_ARC_TEXT_BGCOLOUR;
+ARCSKIP|arcskip yylval.attribType = MSC_ATTR_ARC_SKIP; return TOK_ATTR_ARC_SKIP;
+\.\.\. yylval.arctype = MSC_ARC_DISCO; return TOK_SPECIAL_ARC; /* ... */
+--- yylval.arctype = MSC_ARC_DIVIDER; return TOK_SPECIAL_ARC; /* --- */
+\|\|\| yylval.arctype = MSC_ARC_SPACE; return TOK_SPECIAL_ARC; /* ||| */
+\<-\> yylval.arctype = MSC_ARC_SIGNAL; return TOK_REL_SIG_BI; /* <-> */
+-\> yylval.arctype = MSC_ARC_SIGNAL; return TOK_REL_SIG_TO; /* -> */
+\<- yylval.arctype = MSC_ARC_SIGNAL; return TOK_REL_SIG_FROM; /* <- */
+-- yylval.arctype = MSC_ARC_SIGNAL; return TOK_REL_SIG; /* -- */
+-[Xx] yylval.arctype = MSC_ARC_LOSS; return TOK_REL_LOSS_TO; /* -x */
+[Xx]- yylval.arctype = MSC_ARC_LOSS; return TOK_REL_LOSS_FROM; /* x- */
+\<=\> yylval.arctype = MSC_ARC_METHOD; return TOK_REL_METHOD_BI; /* <=> */
+=\> yylval.arctype = MSC_ARC_METHOD; return TOK_REL_METHOD_TO; /* => */
+\<= yylval.arctype = MSC_ARC_METHOD; return TOK_REL_METHOD_FROM; /* <= */
+== yylval.arctype = MSC_ARC_METHOD; return TOK_REL_METHOD; /* == */
+\<\<\>\> yylval.arctype = MSC_ARC_RETVAL; return TOK_REL_RETVAL_BI; /* <<>> */
+\>\> yylval.arctype = MSC_ARC_RETVAL; return TOK_REL_RETVAL_TO; /* >> */
+\<\< yylval.arctype = MSC_ARC_RETVAL; return TOK_REL_RETVAL_FROM; /* << */
+\.\. yylval.arctype = MSC_ARC_RETVAL; return TOK_REL_RETVAL; /* .. */
+\<:\> yylval.arctype = MSC_ARC_DOUBLE; return TOK_REL_DOUBLE_BI; /* <:> */
+:\> yylval.arctype = MSC_ARC_DOUBLE; return TOK_REL_DOUBLE_TO; /* :> */
+\<: yylval.arctype = MSC_ARC_DOUBLE; return TOK_REL_DOUBLE_FROM; /* <: */
+:: yylval.arctype = MSC_ARC_DOUBLE; return TOK_REL_DOUBLE; /* :: */
+\<\<=\>\> yylval.arctype = MSC_ARC_CALLBACK; return TOK_REL_CALLBACK_BI; /* <<=>> */
+=\>\> yylval.arctype = MSC_ARC_CALLBACK; return TOK_REL_CALLBACK_TO; /* =>> */
+\<\<= yylval.arctype = MSC_ARC_CALLBACK; return TOK_REL_CALLBACK_FROM; /* <<= */
+BOX|box yylval.arctype = MSC_ARC_BOX; return TOK_REL_BOX; /* box */
+ABOX|abox yylval.arctype = MSC_ARC_ABOX; return TOK_REL_ABOX; /* abox */
+RBOX|rbox yylval.arctype = MSC_ARC_RBOX; return TOK_REL_RBOX; /* rbox */
+NOTE|note yylval.arctype = MSC_ARC_NOTE; return TOK_REL_NOTE; /* note */
+[A-Za-z0-9_]+ yylval.string = strdup_s(yytext); return TOK_STRING;
+\"(\\\"|[^\"])*\" yylval.string = trimQstring(strdup_s(yytext)); return TOK_QSTRING;
+= return TOK_EQUAL;
+, return TOK_COMMA;
+\; return TOK_SEMICOLON;
+\{ return TOK_OCBRACKET;
+\} return TOK_CCBRACKET;
+\[ return TOK_OSBRACKET;
+\] return TOK_CSBRACKET;
+\* return TOK_ASTERISK;
+[ \t]+ /* ignore whitespace */;
+
+}
+
+
+<*>.|\n|\r return TOK_UNKNOWN;
+
+%%
+
+/* Handle a new line of input.
+ * This counts the line number and duplicates the string incase we need
+ * it for error reporting. The line is then returned back for parsing
+ * without the newline characters prefixed.
+ */
+static void newline(const char *text, unsigned int n)
+{
+ lex_linenum++;
+ if(lex_line != NULL)
+ {
+ free(lex_line);
+ }
+
+ lex_line = strdup(text + n);
+ yyless(n);
+}
+
+
+/* Trim a multi-line quoted string.
+ * This allows the parsed input quoted strings to span multiple lines of
+ * input but be condensed to only a single line of output e.g.
+ * a->b [label="line 1
+ * line 1 too"];
+ * Will parse to a string such as"line1\n line1 too". This function
+ * will collapse the \n and whitespace into a single space.
+ */
+static char *trimQstring(char *const s)
+{
+ int i = 0, o = 0, skipmode = 0;
+
+ /* Strip leading " */
+ if(s[i] == '\"')
+ {
+ i++;
+ }
+
+ /* Copy body, compacting whitespace after newline sequences */
+ while(s[i] != '\0')
+ {
+ if(s[i] == '\r' || s[i] == '\n' || s[i] == '\f')
+ {
+ skipmode = 1;
+ }
+ else if(!skipmode || !isspace(s[i]))
+ {
+ if(skipmode)
+ {
+ s[o] = ' ';
+ o++;
+ }
+
+ skipmode = 0;
+ s[o] = s[i];
+ o++;
+ }
+
+ i++;
+ }
+
+ /* Null terminate */
+ s[o] = '\0';
+
+ /* Remove trailing " */
+ if(o >= 1 && s[o - 1] == '\"')
+ s[o-1] = '\0';
+
+ return s;
+}
+
+unsigned long lex_getlinenum(void)
+{
+ return lex_linenum;
+}
+
+char *lex_getline(void)
+{
+ return lex_line;
+}
+
+void lex_destroy(void)
+{
+ if(lex_line != NULL)
+ {
+ free(lex_line);
+ lex_line = NULL;
+ }
+}
+
+Boolean lex_getutf8(void)
+{
+ return lex_utf8;
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_msc.c b/libmscgen/mscgen_msc.c
new file mode 100644
index 0000000..0a17395
--- /dev/null
+++ b/libmscgen/mscgen_msc.c
@@ -0,0 +1,804 @@
+/***************************************************************************
+ *
+ * $Id: msc.c 175 2011-02-06 21:07:43Z Michael.McTernan $
+ *
+ * The message sequence parser ADT.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include "mscgen_config.h"
+#include "mscgen_safe.h"
+#include "mscgen_msc.h"
+
+/***************************************************************************
+ * Structures
+ ***************************************************************************/
+
+struct MscEntityTag
+{
+ char *label;
+ struct MscAttribTag *attr;
+ struct MscEntityTag *next;
+};
+
+struct MscEntityListTag
+{
+ unsigned int elements;
+ struct MscEntityTag *head, *tail;
+};
+
+struct MscArcTag
+{
+ char *src, *dst;
+ MscArcType type;
+ unsigned int inputLine;
+ struct MscAttribTag *attr;
+ struct MscArcTag *next;
+};
+
+struct MscArcListTag
+{
+ unsigned int elements;
+ unsigned int parElements;
+ struct MscArcTag *head, *tail;
+};
+
+
+struct MscAttribTag
+{
+ MscAttribType type;
+ char *value;
+ struct MscAttribTag *next;
+};
+
+struct MscOptTag
+{
+ MscOptType type;
+ char *value;
+ struct MscOptTag *next;
+};
+
+struct MscTag
+{
+ struct MscOptTag *optList;
+ struct MscEntityListTag *entityList;
+ struct MscArcListTag *arcList;
+
+ struct MscArcTag *nextArc;
+ struct MscEntityTag *nextEntity;
+};
+
+/***************************************************************************
+ * Local Functions
+ ***************************************************************************/
+
+/** Find come attrbute in an attribute list.
+ *
+ * \param[in] attr Head of the linked list to search.
+ * \param[in] a The attribute type to find.
+ * \retval NULL If the attribute was not found or the passed list was NULL.
+ */
+static const char *findAttrib(const struct MscAttribTag *attr, MscAttribType a)
+{
+ while(attr != NULL && attr->type != a)
+ {
+ attr = attr->next;
+ }
+
+ if(attr != NULL)
+ {
+ return attr->value;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/** Free the memory underlying a list of attributes.
+ */
+static void freeAttribList(struct MscAttribTag *attr)
+{
+ while(attr)
+ {
+ struct MscAttribTag *next = attr->next;
+ free(attr->value);
+ free(attr);
+ attr = next;
+ }
+}
+
+/***************************************************************************
+ * Option Functions
+ ***************************************************************************/
+
+/* Allocate some option and set it's value.
+ */
+struct MscOptTag *MscAllocOpt(MscOptType type,
+ char *value)
+{
+ struct MscOptTag *a = malloc_s(sizeof(struct MscOptTag));
+
+ a->type = type;
+ a->value = value;
+ a->next = NULL;
+
+ return a;
+}
+
+/* Link one or two options together.
+ */
+struct MscOptTag *MscLinkOpt(struct MscOptTag *head,
+ struct MscOptTag *newHead)
+{
+ struct MscOptTag *tail = newHead;
+
+ assert(newHead);
+
+ /* Find the end of the list */
+ while(tail->next)
+ {
+ tail = tail->next;
+ }
+
+ tail->next = head;
+ return newHead;
+}
+
+/* MscPrettyOptType
+ * Returns a string that is the human readable form of the option
+ * code passed to the function.
+ */
+const char *MscPrettyOptType(MscOptType t)
+{
+ switch(t)
+ {
+ case MSC_OPT_HSCALE: return "hscale";
+ case MSC_OPT_WIDTH: return "width";
+ case MSC_OPT_ARCGRADIENT: return "arcgradient";
+ default:
+ return "unknown";
+ }
+}
+
+struct MscOptTag *MscFindOpt(struct MscOptTag *list,
+ MscOptType type)
+{
+ struct MscOptTag *elem = list;
+
+ while(elem && elem->type != type)
+ {
+ elem = elem->next;
+ }
+
+ if(elem && elem->type == type)
+ {
+ return elem;
+ }
+
+ return NULL;
+}
+
+void MscPrintOptList(struct MscOptTag *list)
+{
+ struct MscOptTag *elem = list;
+
+ while(elem)
+ {
+ printf("%p: %s=%s\n", elem, MscPrettyOptType(elem->type), elem->value);
+ elem = elem->next;
+ }
+}
+
+/***************************************************************************
+ * Entity Functions
+ ***************************************************************************/
+
+/* MscAllocEntity
+ * Allocate some entity and set it's name.
+ */
+struct MscEntityTag *MscAllocEntity(char *entityName)
+{
+ struct MscEntityTag *e = malloc_s(sizeof(struct MscEntityListTag));
+
+ e->label = entityName;
+ e->attr = NULL;
+ e->next = NULL;
+
+ return e;
+}
+
+
+/* MscLinkEntity
+ * Link some entity onto a list, possibly producing a new head element.
+ */
+struct MscEntityListTag *MscLinkEntity(struct MscEntityListTag *list,
+ struct MscEntityTag *elem)
+{
+ /* Check if the list has been allocated or not */
+ if(list == NULL)
+ {
+ list = zalloc_s(sizeof(struct MscEntityListTag));
+ }
+
+ /* Check for an empty list */
+ if(list->head == NULL)
+ {
+ list->head = list->tail = elem;
+ }
+ else
+ {
+ /* Add to tail */
+ list->tail->next = elem;
+ list->tail = elem;
+ }
+
+ /* Increment count of elements */
+ list->elements++;
+
+ return list;
+}
+
+
+void MscPrintEntityList(struct MscEntityListTag *list)
+{
+ struct MscEntityTag *elem = list->head;
+
+ while(elem)
+ {
+ printf("%p: %s\n", elem, elem->label);
+ MscPrintAttrib(elem->attr);
+ elem = elem->next;
+ }
+}
+
+/***************************************************************************
+ * Arc Functions
+ ***************************************************************************/
+
+/* MscAllocArc
+ * Allocate an arc, filling in the src and dst entities.
+ */
+struct MscArcTag *MscAllocArc(char *srcEntity,
+ char *dstEntity,
+ MscArcType type,
+ unsigned int inputLine)
+{
+ struct MscArcTag *a = malloc_s(sizeof(struct MscArcTag));
+
+ /* A discontinuity arcs are not between entities */
+ if(type == MSC_ARC_DISCO)
+ {
+ assert(srcEntity == NULL && dstEntity == NULL);
+ }
+
+ a->inputLine = inputLine;
+ a->src = srcEntity;
+ a->dst = dstEntity;
+ a->type = type;
+ a->next = NULL;
+ a->attr = NULL;
+
+ return a;
+}
+
+
+/* MscLinkArc
+ * Link some entity onto a list, possibly producing a new head element.
+ */
+struct MscArcListTag *MscLinkArc(struct MscArcListTag *list,
+ struct MscArcTag *elem)
+{
+ /* Check if the list has been allocated or not */
+ if(list == NULL)
+ {
+ list = zalloc_s(sizeof(struct MscArcListTag));
+ }
+
+ /* Check for an empty list */
+ if(list->head == NULL)
+ {
+ list->head = list->tail = elem;
+ }
+ else
+ {
+ /* Add to tail */
+ list->tail->next = elem;
+ list->tail = elem;
+ }
+
+ /* Increment count of elements */
+ list->elements++;
+ if(elem->type == MSC_ARC_PARALLEL)
+ {
+ /* A parallel arc is a place holder, and indicates the next arc
+ * is on the same line. It also needs to account itself, so subtract
+ * two here.
+ */
+ list->parElements += 2;
+ }
+
+ return list;
+}
+
+
+/* MscPrintArcList
+ * Dump and arc list.
+ */
+void MscPrintArcList(struct MscArcListTag *list)
+{
+ struct MscArcTag *elem = list->head;
+
+ while(elem)
+ {
+ printf("%p: '%s' -> '%s'\n", elem, elem->src, elem->dst);
+ MscPrintAttrib(elem->attr);
+
+ elem = elem->next;
+ }
+}
+
+
+/***************************************************************************
+ * Attribute functions
+ ***************************************************************************/
+
+/* MscAllocAttrib
+ * Allocate some attribute.
+ */
+struct MscAttribTag *MscAllocAttrib(MscAttribType type,
+ char *value)
+{
+ struct MscAttribTag *a = malloc_s(sizeof(struct MscAttribTag));
+
+ a->type = type;
+ a->value = value;
+ a->next = NULL;
+
+ return a;
+}
+
+
+/* MscLinkAttrib
+ * Link some attributes. The ordering of attributes is semi-important
+ * so the list is grown from the tail.
+ */
+struct MscAttribTag *MscLinkAttrib(struct MscAttribTag *head,
+ struct MscAttribTag *newHead)
+{
+ struct MscAttribTag *tail = newHead;
+
+ assert(newHead);
+
+ /* Find the end of the list */
+ while(tail->next)
+ {
+ tail = tail->next;
+ }
+
+ tail->next = head;
+ return newHead;
+}
+
+
+/* MscArcLinkAttrib
+ * Attach some attributes to some arc.
+ */
+void MscArcLinkAttrib(struct MscArcTag *arc,
+ struct MscAttribTag *att)
+{
+ if(arc->attr)
+ {
+ arc->attr = MscLinkAttrib(arc->attr, att);
+ }
+ else
+ {
+ arc->attr = att;
+ }
+}
+
+
+/* MscEntityLinkAttrib
+ * Attach some attributes to some entity.
+ */
+void MscEntityLinkAttrib(struct MscEntityTag *ent,
+ struct MscAttribTag *att)
+{
+ if(ent->attr)
+ {
+ ent->attr = MscLinkAttrib(ent->attr, att);
+ }
+ else
+ {
+ ent->attr = att;
+ }
+}
+
+
+/* MscPrintAttrib
+ * String a human readable version of the passed attribute list to stdout.
+ */
+void MscPrintAttrib(const struct MscAttribTag *att)
+{
+ while(att)
+ {
+ printf(" %s = %s\n", MscPrettyAttribType(att->type), att->value);
+ att = att->next;
+ }
+
+}
+
+
+/* MscPrettyAttribType
+ * Returns a string that is the human readable form of the attribute
+ * code passed to the function.
+ */
+const char *MscPrettyAttribType(MscAttribType t)
+{
+ switch(t)
+ {
+ case MSC_ATTR_LABEL: return "label";
+ case MSC_ATTR_URL: return "url";
+ case MSC_ATTR_ID: return "id";
+ case MSC_ATTR_IDURL: return "idurl";
+ case MSC_ATTR_LINE_COLOUR: return "linecolour";
+ case MSC_ATTR_TEXT_COLOUR: return "textcolour";
+ case MSC_ATTR_TEXT_BGCOLOUR: return "textbgcolour";
+ case MSC_ATTR_ARC_LINE_COLOUR: return "arclinecolour";
+ case MSC_ATTR_ARC_TEXT_COLOUR: return "arctextcolour";
+ case MSC_ATTR_ARC_TEXT_BGCOLOUR: return "arctextbgcolour";
+ case MSC_ATTR_NO_ARROWS: return "noarrows";
+ case MSC_ATTR_BI_ARROWS : return "biarrows";
+ default:
+ return "<unknown>";
+ }
+}
+
+
+/***************************************************************************
+ * MSC Functions
+ ***************************************************************************/
+
+struct MscTag *MscAlloc(struct MscOptTag *optList,
+ struct MscEntityListTag *entityList,
+ struct MscArcListTag *arcList)
+{
+ struct MscTag *m = malloc_s(sizeof(struct MscTag));
+
+ /* Copy the lists */
+ m->optList = optList;
+ m->entityList = entityList;
+ m->arcList = arcList;
+
+ /* Reset the iterators */
+ MscResetEntityIterator(m);
+ MscResetArcIterator(m);
+
+ return m;
+}
+
+void MscFree(struct MscTag *m)
+{
+ struct MscOptTag *opt = m->optList;
+ struct MscEntityTag *entity = m->entityList->head;
+ struct MscArcTag *arc = m->arcList->head;
+
+ while(opt)
+ {
+ struct MscOptTag *next = opt->next;
+
+ free(opt->value);
+ free(opt);
+
+ opt = next;
+ }
+
+ while(entity)
+ {
+ struct MscEntityTag *next = entity->next;
+
+ freeAttribList(entity->attr);
+ free(entity->label);
+ free(entity);
+
+ entity = next;
+ }
+
+ while(arc)
+ {
+ struct MscArcTag *next = arc->next;
+
+ freeAttribList(arc->attr);
+ free(arc->dst);
+ free(arc->src);
+ free(arc);
+
+ arc = next;
+ }
+
+ free(m->entityList);
+ free(m->arcList);
+ free(m);
+}
+
+void MscPrint(struct MscTag *m)
+{
+ printf("Option list (%d options)\n", MscGetNumOpts(m));
+ MscPrintOptList(m->optList);
+
+ printf("Entity list (%d entities, %d parallel)\n",
+ MscGetNumEntities(m), MscGetNumParallelArcs(m));
+ MscPrintEntityList(m->entityList);
+
+ printf("\nArc list (%d arcs)\n", MscGetNumArcs(m));
+ MscPrintArcList(m->arcList);
+}
+
+unsigned int MscGetNumEntities(struct MscTag *m)
+{
+ return m->entityList->elements;
+}
+
+unsigned int MscGetNumArcs(Msc m)
+{
+ return m->arcList->elements;
+}
+
+unsigned int MscGetNumParallelArcs(Msc m)
+{
+ return m->arcList->parElements;
+}
+
+unsigned int MscGetNumOpts(Msc m)
+{
+ struct MscOptTag *elem = m->optList;
+ unsigned int count = 0;
+
+ while(elem)
+ {
+ count++;
+ elem = elem->next;
+ }
+
+ return count;
+}
+
+int MscGetEntityIndex(struct MscTag *m, const char *label)
+{
+ struct MscEntityTag *entity = m->entityList->head;
+ int c = 0;
+
+ assert(label);
+
+ while(entity != NULL && strcmp(entity->label, label) != 0)
+ {
+ entity = entity->next;
+ c++;
+ }
+
+ if(entity == NULL)
+ {
+ return -1;
+ }
+ else
+ {
+ return c;
+ }
+}
+
+void MscResetEntityIterator(struct MscTag *m)
+{
+ m->nextEntity = m->entityList->head;
+}
+
+Boolean MscNextEntity(struct MscTag *m)
+{
+ if(m->nextEntity->next != NULL)
+ {
+ m->nextEntity = m->nextEntity->next;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+const char *MscGetCurrentEntAttrib(struct MscTag *m, MscAttribType a)
+{
+ const char *r;
+
+ if(!m->nextEntity)
+ {
+ return NULL;
+ }
+
+ r = findAttrib(m->nextEntity->attr, a);
+
+ /* If the entity label was sought but not found, return entity name */
+ if(r == NULL && a == MSC_ATTR_LABEL)
+ {
+ return m->nextEntity->label;
+ }
+ else
+ {
+ return r;
+ }
+}
+
+
+const char *MscGetEntAttrib(Msc m, unsigned int entIdx, MscAttribType a)
+{
+ struct MscEntityTag *entity;
+ const char *r;
+
+ /* Find the entity */
+ entity = m->entityList->head;
+ while(entIdx > 0 && entity != NULL)
+ {
+ entity = entity->next;
+ entIdx--;
+ }
+
+ /* Search the attribute list if the entity was found */
+ if(entity)
+ {
+ r = findAttrib(entity->attr, a);
+
+ /* If the entity label was sought but not found, return entity name */
+ if(r == NULL && a == MSC_ATTR_LABEL)
+ {
+ return m->nextEntity->label;
+ }
+ else
+ {
+ return r;
+ }
+ }
+ else
+ {
+ /* Entity was not found */
+ return NULL;
+ }
+}
+
+
+void MscResetArcIterator(struct MscTag *m)
+{
+ m->nextArc = m->arcList->head;
+}
+
+Boolean MscNextArc(struct MscTag *m)
+{
+ if(m->nextArc->next != NULL)
+ {
+ m->nextArc = m->nextArc->next;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+const char *MscGetCurrentArcSource(struct MscTag *m)
+{
+ return m->nextArc ? m->nextArc->src : NULL;
+}
+
+const char *MscGetCurrentArcDest(struct MscTag *m)
+{
+ return m->nextArc ? m->nextArc->dst : NULL;
+}
+
+MscArcType MscGetCurrentArcType(struct MscTag *m)
+{
+ return m->nextArc ? m->nextArc->type : MSC_INVALID_ARC_TYPE;
+}
+
+const char *MscGetCurrentArcAttrib(struct MscTag *m, MscAttribType a)
+{
+ struct MscAttribTag *attr;
+
+ if(!m->nextArc)
+ {
+ return NULL;
+ }
+
+ attr = m->nextArc->attr;
+
+ while(attr != NULL && attr->type != a)
+ {
+ attr = attr->next;
+ }
+
+ if(attr != NULL)
+ {
+ return attr->value;
+ }
+ else
+ {
+ return NULL;
+ }
+
+}
+
+Boolean MscGetOptAsFloat(struct MscTag *m, MscOptType type, float *const f)
+{
+ struct MscOptTag *opt = MscFindOpt(m->optList, type);
+
+ if(opt != NULL)
+ {
+ *f = (float)atof(opt->value);
+ return *f != 0.0f;
+ }
+
+ return FALSE;
+}
+
+unsigned int MscGetCurrentArcInputLine(struct MscTag *m)
+{
+ if(m->nextArc)
+ {
+ return m->nextArc->inputLine;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+Boolean MscGetOptAsBoolean(struct MscTag *m, MscOptType type, Boolean *const b)
+{
+ struct MscOptTag *opt = MscFindOpt(m->optList, type);
+
+ if(opt != NULL)
+ {
+ const char *v = opt->value;
+
+ if(strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0 ||
+ strcasecmp(v, "on") == 0 || strcasecmp(v, "1") == 0)
+ {
+ *b = TRUE;
+ return TRUE;
+ }
+ else if(strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0 ||
+ strcasecmp(v, "off") == 0 || strcasecmp(v, "0") == 0)
+ {
+ *b = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Unrecognised boolean option value '%s'. Valid values are 'true',\n"
+ " 'false', 'yes', 'no', 'on', 'off', '1' and '0'.\n",
+ v);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+/* END OF FILE */
+
diff --git a/libmscgen/mscgen_msc.h b/libmscgen/mscgen_msc.h
new file mode 100644
index 0000000..2c75131
--- /dev/null
+++ b/libmscgen/mscgen_msc.h
@@ -0,0 +1,299 @@
+/***************************************************************************
+ *
+ * $Id: msc.h 175 2011-02-06 21:07:43Z Michael.McTernan $
+ *
+ * The message sequence parser API.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ ***************************************************************************/
+
+#ifndef MSCGEN_MSC_H
+#define MSCGEN_MSC_H
+
+#include "mscgen_bool.h"
+
+/***************************************************************************
+ * Types
+ ***************************************************************************/
+
+/** Msc Options.
+ */
+typedef enum MscOptTypeTag
+{
+ MSC_OPT_HSCALE,
+ MSC_OPT_WIDTH,
+ MSC_OPT_ARCGRADIENT,
+ MSC_OPT_WORDWRAPARCS
+}
+MscOptType;
+
+
+/** Arc attributes.
+ * An arc may have one or more attributes listed in square brackets after
+ * the declaration. This gives an enumerated type for each permissible
+ * attribute.
+ */
+typedef enum MscAttribTypeTag
+{
+ MSC_ATTR_LABEL,
+ MSC_ATTR_ID,
+ MSC_ATTR_URL,
+ MSC_ATTR_IDURL,
+ MSC_ATTR_LINE_COLOUR,
+ MSC_ATTR_TEXT_COLOUR,
+ MSC_ATTR_TEXT_BGCOLOUR,
+ MSC_ATTR_ARC_LINE_COLOUR,
+ MSC_ATTR_ARC_TEXT_COLOUR,
+ MSC_ATTR_ARC_TEXT_BGCOLOUR,
+ MSC_ATTR_NO_ARROWS,
+ MSC_ATTR_BI_ARROWS,
+ MSC_ATTR_ARC_SKIP
+}
+MscAttribType;
+
+
+typedef enum
+{
+ MSC_ARC_METHOD,
+ MSC_ARC_RETVAL,
+ MSC_ARC_SIGNAL,
+ MSC_ARC_CALLBACK,
+ MSC_ARC_DOUBLE,
+ MSC_ARC_DISCO, /* ... Discontinuity in time line */
+ MSC_ARC_DIVIDER, /* --- Divider */
+ MSC_ARC_SPACE, /* ||| */
+ MSC_ARC_PARALLEL, /* Comma instead of semicolon */
+ MSC_ARC_BOX,
+ MSC_ARC_ABOX,
+ MSC_ARC_RBOX,
+ MSC_ARC_NOTE,
+ MSC_ARC_LOSS, /* -x or x- */
+
+ MSC_INVALID_ARC_TYPE
+}
+MscArcType;
+
+
+/***************************************************************************
+ * Abstract types
+ ***************************************************************************/
+
+typedef struct MscTag *Msc;
+
+typedef struct MscOptTag *MscOpt;
+
+typedef struct MscEntityTag *MscEntity;
+
+typedef struct MscEntityListTag *MscEntityList;
+
+typedef struct MscArcTag *MscArc;
+
+typedef struct MscArcListTag *MscArcList;
+
+typedef struct MscAttribTag *MscAttrib;
+
+
+/***************************************************************************
+ * MSC Building Functions
+ ***************************************************************************/
+
+/** Parse some input to build a message sequence chart.
+ * This will parse characters from \a in and build a message sequence chart
+ * ADT.
+ * \retval Msc The message sequence chart, which may equal \a NULL is a
+ * parse error occurred.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+Msc MscParse(FILE *in);
+
+MscEntity MscAllocEntity(char *entityName);
+
+MscEntityList MscLinkEntity(MscEntityList list, MscEntity elem);
+
+void MscPrintEntityList(MscEntityList list);
+
+MscOpt MscAllocOpt(MscOptType type,
+ char *value);
+
+MscOpt MscLinkOpt(MscOpt head,
+ MscOpt newHead);
+
+MscArc MscAllocArc(char *srcEntity,
+ char *dstEntity,
+ MscArcType type,
+ unsigned int inputLine);
+
+MscArcList MscLinkArc (MscArcList list,
+ MscArc elem);
+
+void MscPrintArcList(struct MscArcListTag *list);
+
+MscAttrib MscAllocAttrib(MscAttribType type,
+ char *value);
+
+MscAttrib MscLinkAttrib(MscAttrib head,
+ MscAttrib newHead);
+
+void MscArcLinkAttrib(MscArc arc,
+ MscAttrib att);
+
+void MscEntityLinkAttrib(MscEntity ent,
+ MscAttrib att);
+
+void MscPrintAttrib(const struct MscAttribTag *att);
+
+const char *MscPrettyAttribType(MscAttribType t);
+
+Msc MscAlloc(MscOpt optList,
+ MscEntityList entityList,
+ MscArcList arcList);
+
+void MscFree(struct MscTag *m);
+
+/** Print the passed msc in textual form to stdout.
+ * This prints a human readable format of the parsed msc to stdout. This
+ * is primarily of use in debugging the parser.
+ */
+void MscPrint(Msc m);
+
+unsigned int MscGetNumEntities(Msc m);
+
+unsigned int MscGetNumArcs(Msc m);
+
+unsigned int MscGetNumParallelArcs(Msc m);
+
+unsigned int MscGetNumOpts(Msc m);
+
+/** Get an MSC option, returning the value as a float.
+ *
+ * \param[in] m The MSC to analyse.
+ * \param[in] type The option type to retrieve.
+ * \param[in,out] f Pointer to be filled with parsed value.
+ * \retval TRUE If the option was found and parsed successfully.
+ */
+Boolean MscGetOptAsFloat(struct MscTag *m, MscOptType type, float *const f);
+
+/** Get an MSC option, returning the value as a Boolean.
+ *
+ * \param[in] m The MSC to analyse.
+ * \param[in] type The option type to retrieve.
+ * \param[in,out] b Pointer to be filled with parsed value.
+ * \retval TRUE If the option was found and parsed successfully,
+ * otherwise FALSE in which case *b is unmodified.
+ *
+ */
+Boolean MscGetOptAsBoolean(struct MscTag *m, MscOptType type, Boolean *const b);
+
+/** Get the index of some entity.
+ * This returns the column index for the entity identified by the passed
+ * label.
+ *
+ * \param m The MSC to analyse.
+ * \param label The label to find.
+ * \retval -1 If the label was not found, otherwise the columnn index.
+ */
+int MscGetEntityIndex(struct MscTag *m, const char *label);
+
+/***************************************************************************
+ * Entity processing functions
+ ***************************************************************************/
+
+/** \defgroup EntityFuncs Entity handling functions
+ * @{
+ */
+
+/** Reset the entity interator.
+ * This moves the pointer to the current entity to the head of the list.
+ */
+void MscResetEntityIterator(Msc m);
+
+/** Move to the next entity in the MSC.
+ * \retval TRUE if there is another entity, otherwise FALSE if the end of the
+ * list has been reached.
+ */
+Boolean MscNextEntity(struct MscTag *m);
+
+/** Get the value of some attribute for the current entity.
+ * \retval The attribute string, or NULL if unset.
+ */
+const char *MscGetCurrentEntAttrib(Msc m, MscAttribType a);
+
+/** Get an attribute associated with some entity.
+ * \param[in] entIdx The index of the entity.
+ * \retval The attribute string, or NULL if unset.
+ */
+const char *MscGetEntAttrib(Msc m, unsigned int entIdx, MscAttribType a);
+
+/** @} */
+
+/***************************************************************************
+ * Arc processing functions
+ ***************************************************************************/
+
+/** \defgroup ArcFuncs Arc handling functions
+ * @{
+ */
+
+/** Reset the arc interator.
+ * This moves the pointer to the current arc to the head of the list.
+ */
+void MscResetArcIterator (Msc m);
+
+/** Move to the next arc in the MSC.
+ * \retval TRUE if there is another arc, otherwise FALSE if the end of the
+ * list has been reached.
+ */
+Boolean MscNextArc(struct MscTag *m);
+
+
+/** Get the name of the entity from which the current arc originates.
+ * \retval The label for the entity from which the current arc starts.
+ * The returned string must not be modified.
+ */
+const char *MscGetCurrentArcSource(Msc m);
+
+
+/** Get the name of the entity at which the current arc terminates.
+ * \retval The label for the entity at which the current arc stops.
+ * The returned string must not be modified.
+ */
+const char *MscGetCurrentArcDest(Msc m);
+
+/** Get the type for some arc.
+ *
+ */
+MscArcType MscGetCurrentArcType(struct MscTag *m);
+
+/** Get the value of some attribute for the current arc.
+ * \retval The attribute string, or NULL if unset.
+ */
+const char *MscGetCurrentArcAttrib(Msc m, MscAttribType a);
+
+/** Get the line of the input file at which the current arc was defined.
+ * \retval The line number of the input file.
+ */
+unsigned int MscGetCurrentArcInputLine(Msc m);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MSCGEN_MSC_H */
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_null_out.c b/libmscgen/mscgen_null_out.c
new file mode 100644
index 0000000..4607c71
--- /dev/null
+++ b/libmscgen/mscgen_null_out.c
@@ -0,0 +1,170 @@
+/***************************************************************************
+ *
+ * $Id: null_out.c 112 2010-08-18 12:59:54Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mscgen_adraw_int.h"
+
+/***************************************************************************
+ * API Functions
+ ***************************************************************************/
+
+static unsigned int NullTextWidth(struct ADrawTag *ctx UNUSED,
+ const char *string UNUSED)
+{
+ return 0;
+}
+
+
+static int NullTextHeight(struct ADrawTag *ctx UNUSED)
+{
+ return 0;
+}
+
+
+static void NullLine(struct ADrawTag *ctx UNUSED,
+ unsigned int x1 UNUSED,
+ unsigned int y1 UNUSED,
+ unsigned int x2 UNUSED,
+ unsigned int y2 UNUSED)
+{
+}
+
+
+static void NullDottedLine(struct ADrawTag *ctx UNUSED,
+ unsigned int x1 UNUSED,
+ unsigned int y1 UNUSED,
+ unsigned int x2 UNUSED,
+ unsigned int y2 UNUSED)
+{
+}
+
+
+static void NullTextR(struct ADrawTag *ctx UNUSED,
+ unsigned int x UNUSED,
+ unsigned int y UNUSED,
+ const char *string UNUSED)
+{
+}
+
+
+static void NullTextL(struct ADrawTag *ctx UNUSED,
+ unsigned int x UNUSED,
+ unsigned int y UNUSED,
+ const char *string UNUSED)
+{
+}
+
+
+static void NullTextC(struct ADrawTag *ctx UNUSED,
+ unsigned int x UNUSED,
+ unsigned int y UNUSED,
+ const char *string UNUSED)
+{
+}
+
+
+static void NullFilledRectangle(struct ADrawTag *ctx UNUSED,
+ unsigned int x1 UNUSED,
+ unsigned int y1 UNUSED,
+ unsigned int x2 UNUSED,
+ unsigned int y2 UNUSED)
+{
+}
+
+
+static void NullFilledTriangle(struct ADrawTag *ctx UNUSED,
+ unsigned int x1 UNUSED,
+ unsigned int y1 UNUSED,
+ unsigned int x2 UNUSED,
+ unsigned int y2 UNUSED,
+ unsigned int x3 UNUSED,
+ unsigned int y3 UNUSED)
+{
+}
+
+
+static void NullArc(struct ADrawTag *ctx UNUSED,
+ unsigned int cx UNUSED,
+ unsigned int cy UNUSED,
+ unsigned int w UNUSED,
+ unsigned int h UNUSED,
+ unsigned int s UNUSED,
+ unsigned int e UNUSED)
+{
+}
+
+
+static void NullDottedArc(struct ADrawTag *ctx UNUSED,
+ unsigned int cx UNUSED,
+ unsigned int cy UNUSED,
+ unsigned int w UNUSED,
+ unsigned int h UNUSED,
+ unsigned int s UNUSED,
+ unsigned int e UNUSED)
+{
+}
+
+
+static void NullSetPen (struct ADrawTag *ctx UNUSED,
+ ADrawColour col UNUSED)
+{
+}
+
+
+static void NullSetFontSize(struct ADrawTag *ctx UNUSED,
+ ADrawFontSize size UNUSED)
+{
+}
+
+
+static Boolean NullClose(struct ADrawTag *ctx UNUSED)
+{
+ return TRUE;
+}
+
+
+Boolean NullInit(struct ADrawTag *outContext)
+{
+ /* Fill in the function pointers */
+ outContext->line = NullLine;
+ outContext->dottedLine = NullDottedLine;
+ outContext->textL = NullTextL;
+ outContext->textC = NullTextC;
+ outContext->textR = NullTextR;
+ outContext->textWidth = NullTextWidth;
+ outContext->textHeight = NullTextHeight;
+ outContext->filledRectangle = NullFilledRectangle;
+ outContext->filledTriangle = NullFilledTriangle;
+ outContext->arc = NullArc;
+ outContext->dottedArc = NullDottedArc;
+ outContext->setPen = NullSetPen;
+ outContext->setBgPen = NullSetPen;
+ outContext->setFontSize = NullSetFontSize;
+ outContext->close = NullClose;
+
+ return TRUE;
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_ps_out.c b/libmscgen/mscgen_ps_out.c
new file mode 100644
index 0000000..32f9eae
--- /dev/null
+++ b/libmscgen/mscgen_ps_out.c
@@ -0,0 +1,595 @@
+/***************************************************************************
+ *
+ * $Id: ps_out.c 186 2011-03-01 21:18:19Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#include "mscgen_config.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "mscgen_adraw_int.h"
+#include "mscgen_utf8.h"
+#include "mscgen_safe.h"
+
+/***************************************************************************
+ * Manifest Constants
+ ***************************************************************************/
+
+/** Overall scaling of the Postscript output.
+ */
+#define PS_OUT_SCALE 0.7f
+
+/***************************************************************************
+ * Local types
+ ***************************************************************************/
+
+typedef struct PsContextTag
+{
+ /** Output file. */
+ FILE *of;
+
+ /** Point size of the current font. */
+ int fontPoints;
+
+ /** Current pen colour. */
+ ADrawColour penColour;
+
+ /** Background colour for the pen. */
+ ADrawColour penBgColour;
+}
+PsContext;
+
+typedef struct
+{
+ int capheight, xheight, ascender, descender;
+ int widths[256];
+}
+PsCharMetric;
+
+/** Helvetica character widths.
+ * This gives the width of each character is 1/1000ths of a point.
+ * The values are taken from the Adobe Font Metric file for Hevletica.
+ */
+static const PsCharMetric PsHelvetica =
+{
+ 718, 523, 718, -207,
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 278, 278, 355, 556, 556, 889, 667, 222,
+ 333, 333, 389, 584, 278, 333, 278, 278,
+ 556, 556, 556, 556, 556, 556, 556, 556,
+ 556, 556, 278, 278, 584, 584, 584, 556,
+ 1015, 667, 667, 722, 722, 667, 611, 778,
+ 722, 278, 500, 667, 556, 833, 722, 778,
+ 667, 778, 722, 667, 611, 722, 667, 944,
+ 667, 667, 611, 278, 278, 278, 469, 556,
+ 222, 556, 556, 500, 556, 556, 278, 556,
+ 556, 222, 222, 500, 222, 833, 556, 556,
+ 556, 556, 333, 500, 278, 556, 500, 722,
+ 500, 500, 500, 334, 260, 334, 584, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 333, 556, 556, 167, 556, 556, 556,
+ 556, 191, 333, 556, 333, 333, 500, 500,
+ -1, 556, 556, 556, 278, -1, 537, 350,
+ 222, 333, 333, 556, 1000, 1000, -1, 611,
+ -1, 333, 333, 333, 333, 333, 333, 333,
+ 333, -1, 333, 333, -1, 333, 333, 333,
+ 1000, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1000, -1, 370, -1, -1, -1, -1,
+ 556, 778, 1000, 365, -1, -1, -1, -1,
+ -1, 889, -1, -1, -1, 278, -1, -1,
+ 222, 611, 944, 611, -1, -1, -1, -1
+ }
+};
+
+/***************************************************************************
+ * Helper functions
+ ***************************************************************************/
+
+
+/** Get the context pointer from an ADraw structure.
+ */
+static PsContext *getPsCtx(struct ADrawTag *ctx)
+{
+ return (PsContext *)ctx->internal;
+}
+
+/** Get the context pointer from an ADraw structure.
+ */
+static FILE *getPsFile(struct ADrawTag *ctx)
+{
+ return getPsCtx(ctx)->of;
+}
+
+/** Given a font metric measurement, return device dependent units.
+ * Font metric data is stored as 1/1000th of a point, and therefore
+ * needs to be multiplied by the font point size and divided by
+ * 1000 to give a value in device dependent units.
+ */
+static int getSpace(struct ADrawTag *ctx, long thousanths)
+{
+ return ((thousanths * getPsCtx(ctx)->fontPoints) + 500) / 1000;
+}
+
+/** Write out a line of text, escaping special characters.
+ */
+static void writeEscaped(struct ADrawTag *ctx, const char *string)
+{
+ FILE *f = getPsFile(ctx);
+
+ while(*string != '\0')
+ {
+ unsigned int code, bytes;
+
+ switch(*string)
+ {
+ case '(': fprintf(f, "\\("); break;
+ case ')': fprintf(f, "\\)"); break;
+ default:
+ if(Utf8Decode(string, &code, &bytes))
+ {
+ fprintf(f, "\\%o", code);
+ string += bytes - 1;
+ }
+ else
+ {
+ fputc(*string, f);
+ }
+ break;
+ }
+
+ string++;
+ }
+}
+
+static void setColour(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ float r, g, b;
+
+ /* Extract RGB values */
+ r = (float)((col & 0xff0000) >> 16);
+ g = (float)((col & 0x00ff00) >> 8);
+ b = (float)((col & 0x0000ff) >> 0);
+
+ /* Normalise */
+ r /= 255.0f;
+ g /= 255.0f;
+ b /= 255.0f;
+
+ /* Generate output command */
+ fprintf(getPsFile(ctx), "%f %f %f setrgbcolor\n", r ,g ,b);
+}
+
+/***************************************************************************
+ * API Functions
+ ***************************************************************************/
+
+unsigned int PsTextWidth(struct ADrawTag *ctx,
+ const char *string)
+{
+ unsigned long width = 0;
+
+ while(*string != '\0')
+ {
+ int i = *string & 0xff;
+ unsigned long w = PsHelvetica.widths[i];
+
+ /* Ignore undefined characters */
+ width += w > 0 ? w : 0;
+
+ string++;
+ }
+
+ return getSpace(ctx, width);
+}
+
+
+int PsTextHeight(struct ADrawTag *ctx)
+{
+ return getSpace(ctx, PsHelvetica.ascender - PsHelvetica.descender);
+}
+
+
+void PsLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getPsFile(ctx),
+ "newpath %d %d moveto %d %d lineto stroke\n",
+ x1, 0-y1, x2, 0-y2);
+
+}
+
+
+void PsDottedLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getPsFile(ctx), "[2] 0 setdash\n");
+ PsLine(ctx, x1, y1, x2, y2);
+ fprintf(getPsFile(ctx), "[] 0 setdash\n");
+}
+
+
+void PsFilledRectangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getPsFile(ctx),
+ "newpath "
+ "%d %d moveto "
+ "%d %d lineto "
+ "%d %d lineto "
+ "%d %d lineto "
+ "closepath "
+ "fill\n",
+ x1, 0-y1,
+ x2, 0-y1,
+ x2, 0-y2,
+ x1, 0-y2);
+}
+
+
+void PsTextR(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ /* Push the string and get its width */
+ fprintf(getPsFile(ctx), "(");
+ writeEscaped(ctx, string);
+ fprintf(getPsFile(ctx), ") dup stringwidth\n");
+
+ /* Draw the background box */
+ setColour(ctx, context->penBgColour);
+ fprintf(getPsFile(ctx), "pop " /* Ignore y-value */
+ "dup " /* Duplicate string width */
+ "newpath "
+ "%d %d moveto " /* Bottom left of the box */
+ "0 rlineto " /* Move to bottom right of the box */
+ "0 %d rlineto " /* To top right */
+ "neg 0 rlineto " /* Back to bottom left */
+ "closepath fill\n", /* Done */
+ x, 0-y - getSpace(ctx, PsHelvetica.descender),
+ getSpace(ctx, PsHelvetica.ascender));
+
+ /* Restore pen and show the string */
+ setColour(ctx, context->penColour);
+ fprintf(getPsFile(ctx), "%d %d moveto show\n",
+ x, 0-y - getSpace(ctx, PsHelvetica.descender));
+}
+
+
+void PsTextL(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ /* Draw the background box */
+ setColour(ctx, context->penBgColour);
+ PsFilledRectangle(ctx, x, 0-y, x + 10, 0-y + 10);
+ setColour(ctx, context->penColour);
+
+ fprintf(getPsFile(ctx),
+ "%d %d moveto "
+ "(",
+ x, 0-y - getSpace(ctx, PsHelvetica.descender));
+ writeEscaped(ctx, string);
+ fprintf(getPsFile(ctx),
+ ") dup stringwidth "
+ "pop " /* Ignore y value */
+ "neg " /* Invert x value */
+ "0 "
+ "rmoveto "
+ "show\n");
+}
+
+
+void PsTextC(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ /* Push the string and get its width */
+ fprintf(getPsFile(ctx), "(");
+ writeEscaped(ctx, string);
+ fprintf(getPsFile(ctx), ") dup stringwidth\n");
+
+ /* Draw the background box */
+ setColour(ctx, context->penBgColour);
+ fprintf(getPsFile(ctx), "pop " /* Ignore y-value */
+ "dup dup " /* Duplicate string width twice */
+ "newpath "
+ "%d %d moveto " /* Starting point, centre bottom of box */
+ "2 div neg 0 rmoveto " /* Move to bottom left */
+ "0 rlineto " /* Move to bottom right of the box */
+ "0 %d rlineto " /* To top right */
+ "neg 0 rlineto " /* Back to bottom left */
+ "closepath fill\n", /* Done */
+ x, 0-y,
+ getSpace(ctx, PsHelvetica.ascender));
+
+ /* Restore pen and show the string */
+ setColour(ctx, context->penColour);
+ fprintf(getPsFile(ctx), "%d %d moveto dup stringwidth pop 2 div neg 0 rmoveto show\n",
+ x, 0-y - getSpace(ctx, PsHelvetica.descender));
+}
+
+
+void PsFilledTriangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2,
+ unsigned int x3,
+ unsigned int y3)
+{
+ fprintf(getPsFile(ctx),
+ "newpath "
+ "%d %d moveto "
+ "%d %d lineto "
+ "%d %d lineto "
+ "closepath "
+ "fill\n",
+ x1, 0-y1,
+ x2, 0-y2,
+ x3, 0-y3);
+}
+
+
+void PsFilledCircle(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ unsigned int r)
+{
+ fprintf(getPsFile(ctx),
+ "newpath "
+ "%d %d %d 0 360 arc "
+ "closepath "
+ "fill\n",
+ x, 0-y, r);
+}
+
+
+void PsArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+ fprintf(getPsFile(ctx),
+ "newpath "
+ "%d %d %d %d %d %d ellipse "
+ "stroke\n",
+ cx, 0-cy, w, h, s, e);
+}
+
+
+void PsDottedArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+ fprintf(getPsFile(ctx), "[2] 0 setdash\n");
+ PsArc(ctx, cx, cy, w, h, s, e);
+ fprintf(getPsFile(ctx), "[] 0 setdash\n");
+}
+
+
+void PsSetPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ assert(col != ADRAW_COL_INVALID);
+
+ /* Check if the pen colour has changed */
+ if(context->penColour != col)
+ {
+ setColour(ctx, col);
+
+ /* Store the pen colour */
+ context->penColour = col;
+ }
+}
+
+
+void PsSetBgPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ context->penBgColour = col;
+}
+
+
+void PsSetFontSize(struct ADrawTag *ctx,
+ ADrawFontSize size)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ switch(size)
+ {
+ case ADRAW_FONT_TINY:
+ getPsCtx(ctx)->fontPoints = 8;
+ break;
+
+ case ADRAW_FONT_SMALL:
+ getPsCtx(ctx)->fontPoints = 12;
+ break;
+
+ default:
+ assert(0);
+ }
+
+ fprintf(context->of, "/Helvetica findfont\n");
+ fprintf(context->of, "%d scalefont\n", getPsCtx(ctx)->fontPoints);
+ fprintf(context->of, "setfont\n");
+}
+
+
+Boolean PsClose(struct ADrawTag *ctx)
+{
+ PsContext *context = getPsCtx(ctx);
+
+ /* Close the output file */
+ if(context->of != stdout)
+ {
+ fclose(context->of);
+ }
+
+ /* Free and destroy context */
+ free(context);
+ ctx->internal = NULL;
+
+ return TRUE;
+}
+
+
+
+Boolean PsInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ struct ADrawTag *outContext)
+{
+ PsContext *context;
+
+ /* Create context */
+ context = outContext->internal = malloc_s(sizeof(PsContext));
+ if(context == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Open the output file */
+ if(strcmp(file, "-") == 0)
+ {
+ context->of = stdout;
+ }
+ else
+ {
+ context->of = fopen(file, "wb");
+ if(!context->of)
+ {
+ fprintf(stderr, "PsInit: Failed to open output file '%s': %s\n", file, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /* Write the header */
+ fprintf(context->of, "%%!PS-Adobe-3.0 EPSF-2.0\n"
+ "%%%%BoundingBox: 0 0 %.0f %.0f\n", w * PS_OUT_SCALE, h * PS_OUT_SCALE);
+ fprintf(context->of, "%%%%Creator: mscgen %s\n", PACKAGE_VERSION);
+ fprintf(context->of, "%%%%EndComments\n");
+
+ /* Shrink everything by 70% */
+ fprintf(context->of, "%f %f scale\n", PS_OUT_SCALE, PS_OUT_SCALE);
+
+ /* Create clipping rectangle to constrain dimensions */
+ fprintf(context->of, "0 0 moveto\n");
+ fprintf(context->of, "0 %u lineto\n", h);
+ fprintf(context->of, "%u %u lineto\n", w, h);
+ fprintf(context->of, "%u 0 lineto\n", w);
+ fprintf(context->of, "closepath\n");
+ fprintf(context->of, "clip\n");
+ fprintf(context->of, "%%PageTrailer\n");
+ fprintf(context->of, "%%Page: 1 1\n");
+
+ /* Set default font */
+ fprintf(context->of, "/Helvetica findfont\n");
+ fprintf(context->of, "10 scalefont\n");
+ fprintf(context->of, "setfont\n");
+
+ /* Get the default font size */
+ PsSetFontSize(outContext, ADRAW_FONT_SMALL);
+
+ /* Translate up by the height, y-axis will be inverted */
+ fprintf(context->of, "0 %d translate\n", h);
+
+ /* Arc drawing function */
+ fprintf(context->of, "/mtrx matrix def\n"
+ "/ellipse\n"
+ " { /endangle exch def\n"
+ " /startangle exch def\n"
+ " /ydia exch def\n"
+ " /xdia exch def\n"
+ " /y exch def\n"
+ " /x exch def\n"
+ " /savematrix mtrx currentmatrix def\n"
+ " x y translate\n"
+ " xdia 2 div ydia 2 div scale\n"
+ " 1 -1 scale\n"
+ " 0 0 1 startangle endangle arc\n"
+ " savematrix setmatrix\n"
+ "} def\n");
+
+ /* Set the current pen colours */
+ context->penColour = ADRAW_COL_BLACK;
+ context->penBgColour = ADRAW_COL_WHITE;
+
+ /* Now fill in the function pointers */
+ outContext->line = PsLine;
+ outContext->dottedLine = PsDottedLine;
+ outContext->textL = PsTextL;
+ outContext->textC = PsTextC;
+ outContext->textR = PsTextR;
+ outContext->textWidth = PsTextWidth;
+ outContext->textHeight = PsTextHeight;
+ outContext->filledRectangle = PsFilledRectangle;
+ outContext->filledTriangle = PsFilledTriangle;
+ outContext->filledCircle = PsFilledCircle;
+ outContext->arc = PsArc;
+ outContext->dottedArc = PsDottedArc;
+ outContext->setPen = PsSetPen;
+ outContext->setBgPen = PsSetBgPen;
+ outContext->setFontSize = PsSetFontSize;
+ outContext->close = PsClose;
+
+ return TRUE;
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_safe.c b/libmscgen/mscgen_safe.c
new file mode 100644
index 0000000..c657110
--- /dev/null
+++ b/libmscgen/mscgen_safe.c
@@ -0,0 +1,119 @@
+/***************************************************************************
+ *
+ * $Id: safe.c 152 2010-10-10 14:17:37Z Michael.McTernan $
+ *
+ * This file is part of timgen, a timing diagram renderer.
+ * Copyright (C) 2010 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#define FILE_NAME SAFE
+
+/*****************************************************************************
+ * Header Files
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "mscgen_config.h"
+#include "mscgen_safe.h"
+
+/*****************************************************************************
+ * Preprocessor Macros & Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Typedefs
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Local Variable Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Variable Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Local Function Definitions
+ *****************************************************************************/
+
+static void checkNotNull(void *p, const char *message)
+{
+ if(!p)
+ {
+ fprintf(stderr, "Fatal error: %s\n", message);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*****************************************************************************
+ * Global Function Definitions
+ *****************************************************************************/
+
+void *realloc_s(void *ptr, size_t size)
+{
+ void *r = realloc(ptr, size);
+
+ checkNotNull(r, "realloc() failed");
+
+ return r;
+}
+
+void *malloc_s(size_t size)
+{
+ void *r = malloc(size);
+
+ checkNotNull(r, "malloc() failed");
+
+ return r;
+}
+
+void *zalloc_s(size_t size)
+{
+ void *r = malloc(size);
+
+ checkNotNull(r, "malloc() failed");
+ memset(r, 0, size);
+
+ return r;
+}
+
+char *strdup_s(const char *s)
+{
+ char *r = strdup(s);
+
+ checkNotNull(r, "strdup() failed");
+
+ return r;
+}
+
+const char *mscgen_getenv_s(const char *name)
+{
+ char *r = getenv(name);
+
+ if(r == NULL) r = "";
+
+ return r;
+}
+
+/*****************************************************************************
+ * Unit Test Support
+ *****************************************************************************/
+
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_safe.h b/libmscgen/mscgen_safe.h
new file mode 100644
index 0000000..894c4c8
--- /dev/null
+++ b/libmscgen/mscgen_safe.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *
+ * $Id: safe.h 152 2010-10-10 14:17:37Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#ifndef MSCGEN_SAFE_H
+#define MSCGEN_SAFE_H
+
+/*****************************************************************************
+ * Header Files
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preprocessor Macros & Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Typedefs
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Variable Declarations
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Function Declarations
+ *****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void *realloc_s(void *ptr, size_t size);
+void *malloc_s(size_t size);
+void *zalloc_s(size_t size);
+char *strdup_s(const char *s);
+const char *mscgen_getenv_s(const char *name);
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* MSCGEN_SAFE_H */
diff --git a/libmscgen/mscgen_svg_out.c b/libmscgen/mscgen_svg_out.c
new file mode 100644
index 0000000..73378be
--- /dev/null
+++ b/libmscgen/mscgen_svg_out.c
@@ -0,0 +1,585 @@
+/***************************************************************************
+ *
+ * $Id: svg_out.c 186 2011-03-01 21:18:19Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#include "mscgen_config.h"
+#include <math.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "mscgen_adraw_int.h"
+#include "mscgen_safe.h"
+#include "mscgen_utf8.h"
+
+/***************************************************************************
+ * Local types
+ ***************************************************************************/
+
+typedef struct SvgContextTag
+{
+ /** Output file. */
+ FILE *of;
+
+ /** Current pen colour name. */
+ const char *penColName;
+
+ /** Current background pen colour name. */
+ const char *penBgColName;
+
+ int fontPoints;
+}
+SvgContext;
+
+typedef struct
+{
+ int capheight, xheight, ascender, descender;
+ int widths[256];
+}
+SvgCharMetric;
+
+/** Helvetica character widths.
+ * This gives the width of each character is 1/1000ths of a point.
+ * The values are taken from the Adobe Font Metric file for Hevletica.
+ */
+static const SvgCharMetric SvgHelvetica =
+{
+ 718, 523, 718, -207,
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 278, 278, 355, 556, 556, 889, 667, 222,
+ 333, 333, 389, 584, 278, 333, 278, 278,
+ 556, 556, 556, 556, 556, 556, 556, 556,
+ 556, 556, 278, 278, 584, 584, 584, 556,
+ 1015, 667, 667, 722, 722, 667, 611, 778,
+ 722, 278, 500, 667, 556, 833, 722, 778,
+ 667, 778, 722, 667, 611, 722, 667, 944,
+ 667, 667, 611, 278, 278, 278, 469, 556,
+ 222, 556, 556, 500, 556, 556, 278, 556,
+ 556, 222, 222, 500, 222, 833, 556, 556,
+ 556, 556, 333, 500, 278, 556, 500, 722,
+ 500, 500, 500, 334, 260, 334, 584, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 333, 556, 556, 167, 556, 556, 556,
+ 556, 191, 333, 556, 333, 333, 500, 500,
+ -1, 556, 556, 556, 278, -1, 537, 350,
+ 222, 333, 333, 556, 1000, 1000, -1, 611,
+ -1, 333, 333, 333, 333, 333, 333, 333,
+ 333, -1, 333, 333, -1, 333, 333, 333,
+ 1000, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1000, -1, 370, -1, -1, -1, -1,
+ 556, 778, 1000, 365, -1, -1, -1, -1,
+ -1, 889, -1, -1, -1, 278, -1, -1,
+ 222, 611, 944, 611, -1, -1, -1, -1
+ }
+};
+
+/***************************************************************************
+ * Helper functions
+ ***************************************************************************/
+
+
+/** Get the context pointer from an ADraw structure.
+ */
+static SvgContext *getSvgCtx(struct ADrawTag *ctx)
+{
+ return (SvgContext *)ctx->internal;
+}
+
+/** Get the context pointer from an ADraw structure.
+ */
+static FILE *getSvgFile(struct ADrawTag *ctx)
+{
+ return getSvgCtx(ctx)->of;
+}
+
+static const char *getSvgPen(struct ADrawTag *ctx)
+{
+ return getSvgCtx(ctx)->penColName;
+}
+
+static const char *getSvgBgPen(struct ADrawTag *ctx)
+{
+ return getSvgCtx(ctx)->penBgColName;
+}
+
+/** Given a font metric measurement, return device dependent units.
+ * Font metric data is stored as 1/1000th of a point, and therefore
+ * needs to be multiplied by the font point size and divided by
+ * 1000 to give a value in device dependent units.
+ */
+static int getSpace(struct ADrawTag *ctx, long thousanths)
+{
+ return ((thousanths * getSvgCtx(ctx)->fontPoints) + 500) / 1000;
+}
+
+
+/** Compute a point on an ellipse.
+ * This computes the point on an ellipse.
+ *
+ * \param[in] cx,cy Center of the ellipse.
+ * \param[in] w,h Ellipse width and height.
+ * \param[in] a Angle in degrees.
+ * \param[in,out] x,y Pointer to be populated with result co-ordinates.
+ */
+static void arcPoint(float cx,
+ float cy,
+ float w,
+ float h,
+ float a,
+ unsigned int *x,
+ unsigned int *y)
+{
+ float rad = (float)((a * M_PI) / 180.0f);
+
+ /* Compute point, noting this is for SVG co-ordinate system */
+ *x = (unsigned int)round(cx + ((w / 2.0f) * cos(rad)));
+ *y = (unsigned int)round(cy + ((h / 2.0f) * sin(rad)));
+}
+
+
+/** Write out a line of text, escaping special characters.
+ */
+static void writeEscaped(struct ADrawTag *ctx, const char *string)
+{
+ FILE *f = getSvgFile(ctx);
+
+ while(*string != '\0')
+ {
+ unsigned int code, bytes;
+
+ switch(*string)
+ {
+ case '<': fprintf(f, "&lt;"); break;
+ case '>': fprintf(f, "&gt;"); break;
+ case '"': fprintf(f, "&quot;"); break;
+ case '&': fprintf(f, "&amp;"); break;
+ default:
+ if(Utf8Decode(string, &code, &bytes))
+ {
+ fprintf(f, "&#x%x;", code);
+ string += bytes - 1;
+ }
+ else
+ {
+ fputc(*string, f);
+ }
+ break;
+
+ }
+
+ string++;
+ }
+}
+
+
+
+static void svgRect(struct ADrawTag *ctx,
+ const char *colour,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getSvgFile(ctx),
+ "<polygon fill=\"%s\" points=\"%u,%u %u,%u %u,%u %u,%u\"/>\n",
+ colour,
+ x1, y1,
+ x2, y1,
+ x2, y2,
+ x1, y2);
+}
+
+static const char *svgColour(ADrawColour col)
+{
+ switch(col)
+ {
+ case ADRAW_COL_WHITE:
+ return "white";
+
+ case ADRAW_COL_BLACK:
+ return "black";
+
+ case ADRAW_COL_BLUE:
+ return "blue";
+
+ case ADRAW_COL_RED:
+ return "red";
+
+ case ADRAW_COL_GREEN:
+ return "green";
+
+ default:
+ return NULL;
+ }
+}
+
+
+/***************************************************************************
+ * API Functions
+ ***************************************************************************/
+
+unsigned int SvgTextWidth(struct ADrawTag *ctx,
+ const char *string)
+{
+ unsigned long width = 0;
+
+ while(*string != '\0')
+ {
+ int i = *string & 0xff;
+ unsigned long w = SvgHelvetica.widths[i];
+
+ /* Ignore undefined characters */
+ width += w > 0 ? w : 0;
+
+ string++;
+ }
+
+ return getSpace(ctx, width);
+}
+
+
+int SvgTextHeight(struct ADrawTag *ctx)
+{
+ return getSpace(ctx, SvgHelvetica.ascender - SvgHelvetica.descender);
+}
+
+
+void SvgLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getSvgFile(ctx),
+ "<line x1=\"%u\" y1=\"%u\" x2=\"%u\" y2=\"%u\" stroke=\"%s\"/>\n",
+ x1, y1, x2, y2, getSvgPen(ctx));
+
+}
+
+
+void SvgDottedLine(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ fprintf(getSvgFile(ctx),
+ "<line x1=\"%u\" y1=\"%u\" x2=\"%u\" y2=\"%u\" stroke=\"%s\" stroke-dasharray=\"2,2\"/>\n",
+ x1, y1, x2, y2, getSvgPen(ctx));
+}
+
+
+void SvgTextR(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ SvgContext *context = getSvgCtx(ctx);
+
+ svgRect(ctx, getSvgBgPen(ctx), x - 2, y - SvgTextHeight(ctx) + 1, x + SvgTextWidth(ctx, string), y - 1);
+
+ y += getSpace(ctx, SvgHelvetica.descender);
+
+ fprintf(getSvgFile(ctx),
+ "<text x=\"%u\" y=\"%u\" textLength=\"%u\" font-family=\"Helvetica\" font-size=\"%u\" fill=\"%s\">\n",
+ x - 1, y, SvgTextWidth(ctx, string), context->fontPoints, context->penColName);
+ writeEscaped(ctx, string);
+ fprintf(getSvgFile(ctx), "\n</text>\n");
+}
+
+
+void SvgTextL(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ SvgContext *context = getSvgCtx(ctx);
+
+ svgRect(ctx, getSvgBgPen(ctx), x - (SvgTextWidth(ctx, string) + 2), y - SvgTextHeight(ctx) + 1, x, y - 1);
+
+ y += getSpace(ctx, SvgHelvetica.descender);
+
+ fprintf(getSvgFile(ctx),
+ "<text x=\"%u\" y=\"%u\" textLength=\"%u\" font-family=\"Helvetica\" font-size=\"%u\" fill=\"%s\" text-anchor=\"end\">\n",
+ x, y, SvgTextWidth(ctx, string), context->fontPoints, context->penColName);
+ writeEscaped(ctx, string);
+ fprintf(getSvgFile(ctx), "\n</text>\n");
+
+
+}
+
+
+void SvgTextC(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ const char *string)
+{
+ SvgContext *context = getSvgCtx(ctx);
+ unsigned int hw = SvgTextWidth(ctx, string) / 2;
+
+ svgRect(ctx, getSvgBgPen(ctx), x - (hw + 2), y - SvgTextHeight(ctx) + 1, x + hw, y - 1);
+
+ y += getSpace(ctx, SvgHelvetica.descender);
+
+ fprintf(getSvgFile(ctx),
+ "<text x=\"%u\" y=\"%u\" textLength=\"%u\" font-family=\"Helvetica\" font-size=\"%u\" fill=\"%s\" text-anchor=\"middle\">\n\n",
+ x, y, SvgTextWidth(ctx, string), context->fontPoints, context->penColName);
+ writeEscaped(ctx, string);
+ fprintf(getSvgFile(ctx), "\n</text>\n");
+}
+
+
+void SvgFilledTriangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2,
+ unsigned int x3,
+ unsigned int y3)
+{
+
+ fprintf(getSvgFile(ctx),
+ "<polygon fill=\"%s\" points=\"%u,%u %u,%u %u,%u\"/>\n",
+ getSvgPen(ctx),
+ x1, y1,
+ x2, y2,
+ x3, y3);
+}
+
+
+void SvgFilledCircle(struct ADrawTag *ctx,
+ unsigned int x,
+ unsigned int y,
+ unsigned int r)
+{
+ fprintf(getSvgFile(ctx),
+ "<circle fill=\"%s\" cx=\"%u\" cy=\"%u\" r=\"%u\"/>\n",
+ getSvgPen(ctx),
+ x, y, r);
+}
+
+
+void SvgFilledRectangle(struct ADrawTag *ctx,
+ unsigned int x1,
+ unsigned int y1,
+ unsigned int x2,
+ unsigned int y2)
+{
+ svgRect(ctx, getSvgPen(ctx), x1, y1, x2, y2);
+}
+
+
+void SvgArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+ unsigned int sx, sy, ex, ey;
+
+ /* Get start and end x,y */
+ arcPoint((float)cx, (float)cy, (float)w, (float)h, (float)s, &sx, &sy);
+ arcPoint((float)cx, (float)cy, (float)w, (float)h, (float)e, &ex, &ey);
+
+ fprintf(getSvgFile(ctx),
+ "<path d=\"M %u %u A%u,%u 0 0,1 %u,%u\" stroke=\"%s\" fill=\"none\"/>",
+ sx, sy, w / 2, h / 2, ex, ey, getSvgPen(ctx));
+}
+
+
+void SvgDottedArc(struct ADrawTag *ctx,
+ unsigned int cx,
+ unsigned int cy,
+ unsigned int w,
+ unsigned int h,
+ unsigned int s,
+ unsigned int e)
+{
+ unsigned int sx, sy, ex, ey;
+
+ /* Get start and end x,y */
+ arcPoint((float)cx, (float)cy, (float)w, (float)h, (float)s, &sx, &sy);
+ arcPoint((float)cx, (float)cy, (float)w, (float)h, (float)e, &ex, &ey);
+
+
+ fprintf(getSvgFile(ctx),
+ "<path d=\"M %u %u A%u,%u 0 0,1 %u,%u\" stroke=\"%s\" fill=\"none\" stroke-dasharray=\"2,2\"/>",
+ sx, sy, w / 2, h / 2, ex, ey, getSvgPen(ctx));
+}
+
+
+void SvgSetPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ static char colCmd[10];
+
+ getSvgCtx(ctx)->penColName = svgColour(col);
+ if(getSvgCtx(ctx)->penColName == NULL)
+ {
+ /* Print the RGB value into the local storage */
+ sprintf(colCmd, "#%06X", col);
+
+ /* Now set the colour name to the local store */
+ getSvgCtx(ctx)->penColName = colCmd;
+ }
+}
+
+
+void SvgSetBgPen(struct ADrawTag *ctx,
+ ADrawColour col)
+{
+ static char colCmd[10];
+
+ getSvgCtx(ctx)->penBgColName = svgColour(col);
+ if(getSvgCtx(ctx)->penBgColName == NULL)
+ {
+ /* Print the RGB value into the local storage */
+ sprintf(colCmd, "#%06X", col);
+
+ /* Now set the colour name to the local store */
+ getSvgCtx(ctx)->penBgColName = colCmd;
+ }
+}
+
+
+void SvgSetFontSize(struct ADrawTag *ctx,
+ ADrawFontSize size)
+{
+ SvgContext *context = getSvgCtx(ctx);
+
+ switch(size)
+ {
+ case ADRAW_FONT_TINY:
+ context->fontPoints = 8;
+ break;
+
+ case ADRAW_FONT_SMALL:
+ context->fontPoints = 12;
+ break;
+
+ default:
+ assert(0);
+ }
+
+}
+
+
+Boolean SvgClose(struct ADrawTag *ctx)
+{
+ SvgContext *context = getSvgCtx(ctx);
+
+ /* Close the SVG */
+ fprintf(context->of, "</svg>\n");
+
+ /* Close the output file */
+ if(context->of != stdout)
+ {
+ fclose(context->of);
+ }
+
+ /* Free and destroy context */
+ free(context);
+ ctx->internal = NULL;
+
+ return TRUE;
+}
+
+
+
+Boolean SvgInit(unsigned int w,
+ unsigned int h,
+ const char *file,
+ struct ADrawTag *outContext)
+{
+ SvgContext *context;
+
+ /* Create context */
+ context = outContext->internal = malloc_s(sizeof(SvgContext));
+ if(context == NULL)
+ {
+ return FALSE;
+ }
+
+ /* Open the output file */
+ if(strcmp(file, "-") == 0)
+ {
+ context->of = stdout;
+ }
+ else
+ {
+ context->of = fopen(file, "wb");
+ if(!context->of)
+ {
+ fprintf(stderr, "SvgInit: Failed to open output file '%s': %s\n", file, strerror(errno));
+ return FALSE;
+ }
+ }
+
+ /* Set the initial pen state */
+ SvgSetPen(outContext, ADRAW_COL_BLACK);
+ SvgSetBgPen(outContext, ADRAW_COL_WHITE);
+
+ /* Default to small font */
+ SvgSetFontSize(outContext, ADRAW_FONT_SMALL);
+
+ fprintf(context->of, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"
+ " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
+
+ fprintf(context->of, "<svg version=\"1.1\"\n"
+ " width=\"%upx\" height=\"%upx\"\n"
+ " viewBox=\"0 0 %u %u\"\n"
+ " xmlns=\"http://www.w3.org/2000/svg\" shape-rendering=\"crispEdges\"\n"
+ " stroke-width=\"1\" text-rendering=\"geometricPrecision\">\n",
+ w, h, w, h);
+
+ /* Now fill in the function pointers */
+ outContext->line = SvgLine;
+ outContext->dottedLine = SvgDottedLine;
+ outContext->textL = SvgTextL;
+ outContext->textC = SvgTextC;
+ outContext->textR = SvgTextR;
+ outContext->textWidth = SvgTextWidth;
+ outContext->textHeight = SvgTextHeight;
+ outContext->filledRectangle = SvgFilledRectangle;
+ outContext->filledTriangle = SvgFilledTriangle;
+ outContext->filledCircle = SvgFilledCircle;
+ outContext->arc = SvgArc;
+ outContext->dottedArc = SvgDottedArc;
+ outContext->setPen = SvgSetPen;
+ outContext->setBgPen = SvgSetBgPen;
+ outContext->setFontSize = SvgSetFontSize;
+ outContext->close = SvgClose;
+
+ return TRUE;
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_usage.c b/libmscgen/mscgen_usage.c
new file mode 100644
index 0000000..2126d44
--- /dev/null
+++ b/libmscgen/mscgen_usage.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ *
+ * $Id: main.c 75 2009-07-26 14:45:59Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2010 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+/***************************************************************************
+ * Include Files
+ ***************************************************************************/
+
+#include "mscgen_config.h"
+#include <stdio.h>
+#include "mscgen_usage.h"
+
+/***************************************************************************
+ * Types
+ ***************************************************************************/
+
+/***************************************************************************
+ * Local Variables.
+ ***************************************************************************/
+
+/***************************************************************************
+ * Functions
+ ***************************************************************************/
+
+/** Print program usage and return.
+ */
+void Usage(void)
+{
+ printf(
+"Usage: mscgen -T <type> [-o <file>] [-i] <infile>\n"
+" mscgen -l\n"
+"\n"
+"Where:\n"
+" -T <type> Specifies the output file type, which maybe one of 'png', 'eps',\n"
+" 'svg' or 'ismap'\n"
+" -i <infile> The file from which to read input. If omitted or specified as\n"
+" '-', input will be read from stdin. The '-i' flag maybe\n"
+" omitted if <infile> is specified as the last option on the\n"
+" command line.\n"
+" -o <file> Write output to the named file. This option must be specified if \n"
+" input is taken from stdin, otherwise the output filename\n"
+" defaults to <infile>.<type>. This may also be specified as '-'\n"
+" to write output directly to stdout.\n"
+#ifdef USE_FREETYPE
+" -F <font> Use specified font for PNG output. This must be a font specifier\n"
+" compatbile with fontconfig (see 'fc-list'), and overrides the\n"
+" MSCGEN_FONT environment variable if also set.\n"
+#endif
+" -p Print parsed msc output (for parser debug).\n"
+" -l Display program licence and exit.\n"
+"\n"
+"Mscgen version %s, Copyright (C) 2010 Michael C McTernan,\n"
+" Michael.McTernan.2001@cs.bris.ac.uk\n"
+"Mscgen comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n"
+"welcome to redistribute it under certain conditions; type `mscgen -l' for\n"
+"details.\n"
+"\n"
+"PNG rendering by libgd, www.libgd.org\n"
+"\n",
+PACKAGE_VERSION);
+}
+
+
+/** Print program licence and return.
+ */
+void Licence(void)
+{
+ printf(
+"Mscgen, a message sequence chart renderer.\n"
+"Copyright (C) 2010 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk\n"
+"\n"
+"TTPCom Ltd., hereby disclaims all copyright interest in the program `mscgen'\n"
+"(which renders message sequence charts) written by Michael McTernan.\n"
+"\n"
+"Rob Meades of TTPCom Ltd, 1 August 2005\n"
+"Rob Meades, director of Software\n"
+"\n"
+"This program is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License as published by\n"
+"the Free Software Foundation; either version 2 of the License, or\n"
+"(at your option) any later version.\n"
+"\n"
+"This program is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"GNU General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this program; if not, write to the Free Software\n"
+"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA\n");
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_usage.h b/libmscgen/mscgen_usage.h
new file mode 100644
index 0000000..0aab946
--- /dev/null
+++ b/libmscgen/mscgen_usage.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *
+ * $Id: safe.h 59 2009-07-18 17:31:50Z Michael.McTernan $
+ *
+ * This file is part of mscgen, a message sequence chart renderer.
+ * Copyright (C) 2005 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+#ifndef MSCGEN_USAGE_H
+#define MSCGEN_USAGE_H
+
+/*****************************************************************************
+ * Header Files
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preprocessor Macros & Constants
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Typedefs
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Variable Declarations
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global Function Declarations
+ *****************************************************************************/
+
+void Usage(void);
+void Licence(void);
+
+#endif /* MSCGEN_USAGE_H */
diff --git a/libmscgen/mscgen_utf8.c b/libmscgen/mscgen_utf8.c
new file mode 100644
index 0000000..9614c47
--- /dev/null
+++ b/libmscgen/mscgen_utf8.c
@@ -0,0 +1,103 @@
+/***************************************************************************
+ *
+ * $Id: utf8.c 93 2009-08-24 20:57:31Z Michael.McTernan $
+ *
+ * UTF8 decode routine.
+ * Copyright (C) 2008 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ **************************************************************************/
+
+/**************************************************************************
+ * Includes
+ **************************************************************************/
+
+#include "mscgen_utf8.h"
+
+/**************************************************************************
+ * Manfest Constants
+ **************************************************************************/
+
+/**************************************************************************
+ * Macros
+ **************************************************************************/
+
+/**************************************************************************
+ * Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Local Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Local Functions
+ **************************************************************************/
+
+/** Count leading ones from the MSB.
+ */
+static unsigned int clo(char c)
+{
+ unsigned int t = 0;
+
+ while((c & (0x80 >> t)) != 0 && t < 8)
+ {
+ t++;
+ }
+
+ return t;
+}
+
+/**************************************************************************
+ * Global Functions
+ **************************************************************************/
+
+Boolean Utf8Decode(const char *s, unsigned int *r, unsigned int *bytes)
+{
+ if((*s & 0x80) == 0)
+ {
+ return FALSE;
+ }
+ else
+ {
+ unsigned int t;
+
+ /* Set default return values */
+ *bytes = clo(*s);
+ *r = 0;
+
+ /* Loop through string, checking for null termination */
+ for(t = 0; t < *bytes && s[t] != '\0'; t++)
+ {
+ /* Shift up previous bits */
+ *r <<= 6;
+
+ /* Add the required bits */
+ if(t == 0)
+ {
+ *r |= s[t] & (0xff >> (*bytes + 1));
+ }
+ else
+ {
+ *r |= s[t] & 0x3f;
+ }
+ }
+
+ /* Success if no NULL was encoutered */
+ return t == *bytes;
+ }
+}
+
+/* END OF FILE */
diff --git a/libmscgen/mscgen_utf8.h b/libmscgen/mscgen_utf8.h
new file mode 100644
index 0000000..a0ea954
--- /dev/null
+++ b/libmscgen/mscgen_utf8.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ *
+ * $Id: utf8.h 93 2009-08-24 20:57:31Z Michael.McTernan $
+ *
+ * UTF8 decode routine interface.
+ * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef MSCGEN_UTF8_H
+#define MSCGEN_UTF8_H
+
+/**************************************************************************
+ * Includes
+ **************************************************************************/
+
+#include "mscgen_bool.h"
+
+/**************************************************************************
+ * Macros
+ **************************************************************************/
+
+/**************************************************************************
+ * Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Prototypes
+ **************************************************************************/
+
+Boolean Utf8Decode(const char *s, unsigned int *r, unsigned int *bytes);
+
+#endif
+
+/* END OF FILE */
diff --git a/qtools/Doxyfile b/qtools/Doxyfile
index af84df1..109d3dc 100644
--- a/qtools/Doxyfile
+++ b/qtools/Doxyfile
@@ -280,7 +280,6 @@ GENERATE_TAGFILE = ../qtools_docs/qtools.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
-PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f4e1231..06e0e44 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,8 +3,10 @@
include_directories(
${CMAKE_SOURCE_DIR}/qtools
${CMAKE_SOURCE_DIR}/libmd5
+ ${CMAKE_SOURCE_DIR}/liblodepng
+ ${CMAKE_SOURCE_DIR}/libmscgen
${CMAKE_SOURCE_DIR}/libversion
- ${CMAKE_SOURCE_DIR}/vhdlparser/
+ ${CMAKE_SOURCE_DIR}/vhdlparser
${CMAKE_SOURCE_DIR}/src
${CLANG_INCLUDEDIR}
${GENERATED_SRC}
@@ -15,7 +17,7 @@ file(MAKE_DIRECTORY ${GENERATED_SRC})
file(GLOB LANGUAGE_FILES "${CMAKE_SOURCE_DIR}/src/translator_??.h")
# instead of increasebuffer.py
-add_definitions(-DYY_BUF_SIZE=262144 -DYY_READ_BUF_SIZE=262144)
+add_definitions(-DYY_BUF_SIZE=${enlarge_lex_buffers} -DYY_READ_BUF_SIZE=${enlarge_lex_buffers})
# generate settings.h
file(GENERATE OUTPUT ${GENERATED_SRC}/settings.h
@@ -38,6 +40,10 @@ add_custom_command(
OUTPUT ${GENERATED_SRC}/configvalues.h
)
set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
+add_custom_target(
+ generate_configvalues_header
+ DEPENDS ${GENERATED_SRC}/configvalues.h
+)
# configvalues.cpp
add_custom_command(
@@ -175,6 +181,16 @@ add_library(_doxygen STATIC
docparser.cpp
docsets.cpp
dot.cpp
+ dotcallgraph.cpp
+ dotclassgraph.cpp
+ dotdirdeps.cpp
+ dotfilepatcher.cpp
+ dotgfxhierarchytable.cpp
+ dotgraph.cpp
+ dotgroupcollaboration.cpp
+ dotincldepgraph.cpp
+ dotnode.cpp
+ dotrunner.cpp
doxygen.cpp
eclipsehelp.cpp
emoji.cpp
@@ -197,7 +213,6 @@ add_library(_doxygen STATIC
latexdocvisitor.cpp
latexgen.cpp
layout.cpp
- lodepng.cpp
mandocvisitor.cpp
mangen.cpp
sqlite3gen.cpp
@@ -233,6 +248,7 @@ add_library(_doxygen STATIC
xmlgen.cpp
docbookvisitor.cpp
docbookgen.cpp
+ docgroup.cpp
)
add_executable(doxygen main.cpp)
@@ -262,6 +278,8 @@ target_link_libraries(doxygen
doxycfg
qtools
md5
+ lodepng
+ mscgen
version
vhdlparser
${SQLITE3_LIBRARIES}
diff --git a/src/clangparser.cpp b/src/clangparser.cpp
index f24ec0a..271b99f 100644
--- a/src/clangparser.cpp
+++ b/src/clangparser.cpp
@@ -782,7 +782,7 @@ void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd,
g_currentMemberDef && d->definitionType()==Definition::TypeMember &&
(g_currentMemberDef!=d || g_currentLine<line)) // avoid self-reference
{
- addDocCrossReference(g_currentMemberDef,(MemberDef*)d);
+ addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef *>(d));
}
writeMultiLineCodeLink(ol,fd,line,column,d,text);
}
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 5ea8cea..a7b59c1 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -33,6 +33,8 @@
#include "example.h"
#include "outputlist.h"
#include "dot.h"
+#include "dotclassgraph.h"
+#include "dotrunner.h"
#include "defargs.h"
#include "debug.h"
#include "docparser.h"
@@ -61,6 +63,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
/** Destroys a compound definition. */
~ClassDefImpl();
+ virtual ClassDef *resolveAlias() { return this; }
virtual DefType definitionType() const { return TypeClass; }
virtual QCString getOutputFileBase() const;
virtual QCString getInstanceOutputFileBase() const;
@@ -92,7 +95,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual bool isSubClass(ClassDef *bcd,int level=0) const;
virtual bool isAccessibleMember(const MemberDef *md) const;
virtual QDict<ClassDef> *getTemplateInstances() const;
- virtual ClassDef *templateMaster() const;
+ virtual const ClassDef *templateMaster() const;
virtual bool isTemplate() const;
virtual IncludeInfo *includeInfo() const;
virtual UsesClassDict *usedImplementationClasses() const;
@@ -120,7 +123,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual const QList<MemberList> &getMemberLists() const;
virtual MemberGroupSDict *getMemberGroupSDict() const;
virtual QDict<int> *getTemplateBaseClassNames() const;
- virtual ClassDef *getVariableInstance(const char *templSpec);
+ virtual ClassDef *getVariableInstance(const char *templSpec) const;
virtual bool isUsedOnly() const;
virtual QCString anchor() const;
virtual bool isEmbeddedInOuterScope() const;
@@ -141,6 +144,10 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual QCString getMemberListFileName() const;
virtual bool subGrouping() const;
virtual bool isSliceLocal() const;
+ virtual bool hasNonReferenceSuperClass() const;
+ virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
+ const QCString &templSpec,bool &freshInstance) const;
+
virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0);
virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0);
virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force);
@@ -153,9 +160,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual void setSubGrouping(bool enabled);
virtual void setProtection(Protection p);
virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs);
- virtual void addInnerCompound(Definition *d);
- virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
- const QCString &templSpec,bool &freshInstance);
+ virtual void addInnerCompound(const Definition *d);
virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot);
virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot);
virtual void setIsStatic(bool b);
@@ -164,9 +169,9 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual void setClassSpecifier(uint64 spec);
virtual void setTemplateArguments(ArgumentList *al);
virtual void setTemplateBaseClassNames(QDict<int> *templateNames);
- virtual void setTemplateMaster(ClassDef *tm);
+ virtual void setTemplateMaster(const ClassDef *tm);
virtual void setTypeConstraints(ArgumentList *al);
- virtual void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec);
+ virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec);
virtual void makeTemplateArgument(bool b=TRUE);
virtual void setCategoryOf(ClassDef *cd);
virtual void setUsedOnly(bool b);
@@ -182,75 +187,79 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef
virtual void mergeMembers();
virtual void sortMemberLists();
virtual void distributeMemberGroupDocumentation();
- virtual void writeDocumentation(OutputList &ol);
- virtual void writeDocumentationForInnerClasses(OutputList &ol);
- virtual void writeMemberPages(OutputList &ol);
- virtual void writeMemberList(OutputList &ol);
- virtual void writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup,
- ClassDef *inheritedFrom,const char *inheritId);
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *md) const;
- virtual void writeSummaryLinks(OutputList &ol);
+ virtual void writeDocumentation(OutputList &ol) const;
+ virtual void writeDocumentationForInnerClasses(OutputList &ol) const;
+ virtual void writeMemberPages(OutputList &ol) const;
+ virtual void writeMemberList(OutputList &ol) const;
+ virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,
+ const ClassDef *inheritedFrom,const char *inheritId) const;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const;
+ virtual void writeSummaryLinks(OutputList &ol) const;
virtual void reclassifyMember(MemberDef *md,MemberType t);
- virtual void writeInlineDocumentation(OutputList &ol);
+ virtual void writeInlineDocumentation(OutputList &ol) const;
virtual void writeDeclarationLink(OutputList &ol,bool &found,
- const char *header,bool localNames);
+ const char *header,bool localNames) const;
virtual void removeMemberFromLists(MemberDef *md);
+ virtual void setAnonymousEnumType();
+ virtual void countMembers();
+
virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
- ClassDef *inheritedFrom,const QCString &inheritId);
- virtual int countMembersIncludingGrouped(MemberListType lt,ClassDef *inheritedFrom,bool additional);
- virtual int countInheritanceNodes();
+ const ClassDef *inheritedFrom,const QCString &inheritId) const;
virtual void writeTagFile(FTextStream &);
- virtual void setVisited(bool visited) { m_visited = visited; }
+ virtual void setVisited(bool visited) const { m_visited = visited; }
virtual bool isVisited() const { return m_visited; }
- virtual bool hasNonReferenceSuperClass() const;
- virtual int countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom,
- int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses);
+ virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const;
+ virtual int countInheritanceNodes() const;
+ virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
+ int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const;
virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title,
- const char *subTitle=0,bool showInline=FALSE,ClassDef *inheritedFrom=0,
+ const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0,
int lt2=-1,bool invert=FALSE,bool showAlways=FALSE,
- QPtrDict<void> *visitedClasses=0);
+ QPtrDict<void> *visitedClasses=0) const;
private:
- bool m_visited;
+ mutable bool m_visited;
void addUsedInterfaceClasses(MemberDef *md,const char *typeStr);
- void showUsedFiles(OutputList &ol);
+ void showUsedFiles(OutputList &ol) const;
- void writeDocumentationContents(OutputList &ol,const QCString &pageTitle);
+ void writeDocumentationContents(OutputList &ol,const QCString &pageTitle) const;
void internalInsertMember(MemberDef *md,Protection prot,bool addToAllList);
void addMemberToList(MemberListType lt,MemberDef *md,bool isBrief);
MemberList *createMemberList(MemberListType lt);
- void writeInheritedMemberDeclarations(OutputList &ol,MemberListType lt,int lt2,const QCString &title,ClassDef *inheritedFrom,bool invert,bool showAlways,QPtrDict<void> *visitedClasses);
- void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE);
- void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt);
- void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,ClassDef *inheritedFrom,const char *inheritId);
- void writeBriefDescription(OutputList &ol,bool exampleFlag);
+ void writeInheritedMemberDeclarations(OutputList &ol,MemberListType lt,int lt2,const QCString &title,
+ const ClassDef *inheritedFrom,bool invert,
+ bool showAlways,QPtrDict<void> *visitedClasses) const;
+ void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE) const;
+ void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const;
+ void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,const ClassDef *inheritedFrom,const char *inheritId) const;
+ void writeBriefDescription(OutputList &ol,bool exampleFlag) const;
void writeDetailedDescription(OutputList &ol,const QCString &pageType,bool exampleFlag,
- const QCString &title,const QCString &anchor=QCString());
- void writeIncludeFiles(OutputList &ol);
- void writeIncludeFilesForSlice(OutputList &ol);
+ const QCString &title,const QCString &anchor=QCString()) const;
+ void writeIncludeFiles(OutputList &ol) const;
+ void writeIncludeFilesForSlice(OutputList &ol) const;
//void writeAllMembersLink(OutputList &ol);
- void writeInheritanceGraph(OutputList &ol);
- void writeCollaborationGraph(OutputList &ol);
- void writeMemberGroups(OutputList &ol,bool showInline=FALSE);
- void writeNestedClasses(OutputList &ol,const QCString &title);
- void writeInlineClasses(OutputList &ol);
- void startMemberDeclarations(OutputList &ol);
- void endMemberDeclarations(OutputList &ol);
- void startMemberDocumentation(OutputList &ol);
- void endMemberDocumentation(OutputList &ol);
- void writeAuthorSection(OutputList &ol);
- void writeMoreLink(OutputList &ol,const QCString &anchor);
- void writeDetailedDocumentationBody(OutputList &ol);
-
- int countAdditionalInheritedMembers();
- void writeAdditionalInheritedMembers(OutputList &ol);
- void addClassAttributes(OutputList &ol);
+ void writeInheritanceGraph(OutputList &ol) const;
+ void writeCollaborationGraph(OutputList &ol) const;
+ void writeMemberGroups(OutputList &ol,bool showInline=FALSE) const;
+ void writeNestedClasses(OutputList &ol,const QCString &title) const;
+ void writeInlineClasses(OutputList &ol) const;
+ void startMemberDeclarations(OutputList &ol) const;
+ void endMemberDeclarations(OutputList &ol) const;
+ void startMemberDocumentation(OutputList &ol) const;
+ void endMemberDocumentation(OutputList &ol) const;
+ void writeAuthorSection(OutputList &ol) const;
+ void writeMoreLink(OutputList &ol,const QCString &anchor) const;
+ void writeDetailedDocumentationBody(OutputList &ol) const;
+
+ int countAdditionalInheritedMembers() const;
+ void writeAdditionalInheritedMembers(OutputList &ol) const;
+ void addClassAttributes(OutputList &ol) const;
int countInheritedDecMembers(MemberListType lt,
- ClassDef *inheritedFrom,bool invert,bool showAlways,
- QPtrDict<void> *visitedClasses);
+ const ClassDef *inheritedFrom,bool invert,bool showAlways,
+ QPtrDict<void> *visitedClasses) const;
void getTitleForMemberListType(MemberListType type,
- QCString &title,QCString &subtitle);
+ QCString &title,QCString &subtitle) const;
QCString includeStatement() const;
void addTypeConstraint(const QCString &typeConstraint,const QCString &type);
@@ -267,6 +276,265 @@ ClassDef *createClassDef(
{
return new ClassDefImpl(fileName,startLine,startColumn,name,ct,ref,fName,isSymbol,isJavaEnum);
}
+//-----------------------------------------------------------------------------
+
+class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef
+{
+ public:
+ ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) : DefinitionAliasImpl(newScope,cd) {}
+ virtual ~ClassDefAliasImpl() {}
+ virtual DefType definitionType() const { return TypeClass; }
+
+ const ClassDef *getCdAlias() const { return dynamic_cast<const ClassDef*>(getAlias()); }
+ virtual ClassDef *resolveAlias() { return const_cast<ClassDef*>(getCdAlias()); }
+
+ virtual QCString getOutputFileBase() const
+ { return getCdAlias()->getOutputFileBase(); }
+ virtual QCString getInstanceOutputFileBase() const
+ { return getCdAlias()->getInstanceOutputFileBase(); }
+ virtual QCString getSourceFileBase() const
+ { return getCdAlias()->getSourceFileBase(); }
+ virtual QCString getReference() const
+ { return getCdAlias()->getReference(); }
+ virtual bool isReference() const
+ { return getCdAlias()->isReference(); }
+ virtual bool isLocal() const
+ { return getCdAlias()->isLocal(); }
+ virtual ClassSDict *getClassSDict() const
+ { return getCdAlias()->getClassSDict(); }
+ virtual bool hasDocumentation() const
+ { return getCdAlias()->hasDocumentation(); }
+ virtual bool hasDetailedDescription() const
+ { return getCdAlias()->hasDetailedDescription(); }
+ virtual QCString collaborationGraphFileName() const
+ { return getCdAlias()->collaborationGraphFileName(); }
+ virtual QCString inheritanceGraphFileName() const
+ { return getCdAlias()->inheritanceGraphFileName(); }
+ virtual QCString displayName(bool includeScope=TRUE) const
+ { return getCdAlias()->displayName(includeScope); }
+ virtual CompoundType compoundType() const
+ { return getCdAlias()->compoundType(); }
+ virtual QCString compoundTypeString() const
+ { return getCdAlias()->compoundTypeString(); }
+ virtual BaseClassList *baseClasses() const
+ { return getCdAlias()->baseClasses(); }
+ virtual BaseClassList *subClasses() const
+ { return getCdAlias()->subClasses(); }
+ virtual MemberNameInfoSDict *memberNameInfoSDict() const
+ { return getCdAlias()->memberNameInfoSDict(); }
+ virtual Protection protection() const
+ { return getCdAlias()->protection(); }
+ virtual bool isLinkableInProject() const
+ { return getCdAlias()->isLinkableInProject(); }
+ virtual bool isLinkable() const
+ { return getCdAlias()->isLinkable(); }
+ virtual bool isVisibleInHierarchy() const
+ { return getCdAlias()->isVisibleInHierarchy(); }
+ virtual bool visibleInParentsDeclList() const
+ { return getCdAlias()->visibleInParentsDeclList(); }
+ virtual ArgumentList *templateArguments() const
+ { return getCdAlias()->templateArguments(); }
+ virtual NamespaceDef *getNamespaceDef() const
+ { return getCdAlias()->getNamespaceDef(); }
+ virtual FileDef *getFileDef() const
+ { return getCdAlias()->getFileDef(); }
+ virtual MemberDef *getMemberByName(const QCString &s) const
+ { return getCdAlias()->getMemberByName(s); }
+ virtual bool isBaseClass(const ClassDef *bcd,bool followInstances,int level=0) const
+ { return getCdAlias()->isBaseClass(bcd,followInstances,level); }
+ virtual bool isSubClass(ClassDef *bcd,int level=0) const
+ { return getCdAlias()->isSubClass(bcd,level); }
+ virtual bool isAccessibleMember(const MemberDef *md) const
+ { return getCdAlias()->isAccessibleMember(md); }
+ virtual QDict<ClassDef> *getTemplateInstances() const
+ { return getCdAlias()->getTemplateInstances(); }
+ virtual const ClassDef *templateMaster() const
+ { return getCdAlias()->templateMaster(); }
+ virtual bool isTemplate() const
+ { return getCdAlias()->isTemplate(); }
+ virtual IncludeInfo *includeInfo() const
+ { return getCdAlias()->includeInfo(); }
+ virtual UsesClassDict *usedImplementationClasses() const
+ { return getCdAlias()->usedImplementationClasses(); }
+ virtual UsesClassDict *usedByImplementationClasses() const
+ { return getCdAlias()->usedByImplementationClasses(); }
+ virtual UsesClassDict *usedInterfaceClasses() const
+ { return getCdAlias()->usedInterfaceClasses(); }
+ virtual ConstraintClassDict *templateTypeConstraints() const
+ { return getCdAlias()->templateTypeConstraints(); }
+ virtual bool isTemplateArgument() const
+ { return getCdAlias()->isTemplateArgument(); }
+ virtual Definition *findInnerCompound(const char *name) const
+ { return getCdAlias()->findInnerCompound(name); }
+ virtual void getTemplateParameterLists(QList<ArgumentList> &lists) const
+ { return getCdAlias()->getTemplateParameterLists(lists); }
+ virtual QCString qualifiedNameWithTemplateParameters(
+ QList<ArgumentList> *actualParams=0,int *actualParamIndex=0) const
+ { return getCdAlias()->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); }
+ virtual bool isAbstract() const
+ { return getCdAlias()->isAbstract(); }
+ virtual bool isObjectiveC() const
+ { return getCdAlias()->isObjectiveC(); }
+ virtual bool isFortran() const
+ { return getCdAlias()->isFortran(); }
+ virtual bool isCSharp() const
+ { return getCdAlias()->isCSharp(); }
+ virtual bool isFinal() const
+ { return getCdAlias()->isFinal(); }
+ virtual bool isSealed() const
+ { return getCdAlias()->isSealed(); }
+ virtual bool isPublished() const
+ { return getCdAlias()->isPublished(); }
+ virtual bool isExtension() const
+ { return getCdAlias()->isExtension(); }
+ virtual bool isForwardDeclared() const
+ { return getCdAlias()->isForwardDeclared(); }
+ virtual bool isInterface() const
+ { return getCdAlias()->isInterface(); }
+ virtual ClassDef *categoryOf() const
+ { return getCdAlias()->categoryOf(); }
+ virtual QCString className() const
+ { return getCdAlias()->className(); }
+ virtual MemberList *getMemberList(MemberListType lt) const
+ { return getCdAlias()->getMemberList(lt); }
+ virtual const QList<MemberList> &getMemberLists() const
+ { return getCdAlias()->getMemberLists(); }
+ virtual MemberGroupSDict *getMemberGroupSDict() const
+ { return getCdAlias()->getMemberGroupSDict(); }
+ virtual QDict<int> *getTemplateBaseClassNames() const
+ { return getCdAlias()->getTemplateBaseClassNames(); }
+ virtual ClassDef *getVariableInstance(const char *templSpec) const
+ { return getCdAlias()->getVariableInstance(templSpec); }
+ virtual bool isUsedOnly() const
+ { return getCdAlias()->isUsedOnly(); }
+ virtual QCString anchor() const
+ { return getCdAlias()->anchor(); }
+ virtual bool isEmbeddedInOuterScope() const
+ { return getCdAlias()->isEmbeddedInOuterScope(); }
+ virtual bool isSimple() const
+ { return getCdAlias()->isSimple(); }
+ virtual const ClassList *taggedInnerClasses() const
+ { return getCdAlias()->taggedInnerClasses(); }
+ virtual ClassDef *tagLessReference() const
+ { return getCdAlias()->tagLessReference(); }
+ virtual MemberDef *isSmartPointer() const
+ { return getCdAlias()->isSmartPointer(); }
+ virtual bool isJavaEnum() const
+ { return getCdAlias()->isJavaEnum(); }
+ virtual bool isGeneric() const
+ { return getCdAlias()->isGeneric(); }
+ virtual bool isAnonymous() const
+ { return getCdAlias()->isAnonymous(); }
+ virtual const ClassSDict *innerClasses() const
+ { return getCdAlias()->innerClasses(); }
+ virtual QCString title() const
+ { return getCdAlias()->title(); }
+ virtual QCString generatedFromFiles() const
+ { return getCdAlias()->generatedFromFiles(); }
+ virtual const FileList &usedFiles() const
+ { return getCdAlias()->usedFiles(); }
+ virtual const ArgumentList *typeConstraints() const
+ { return getCdAlias()->typeConstraints(); }
+ virtual const ExampleSDict *exampleList() const
+ { return getCdAlias()->exampleList(); }
+ virtual bool hasExamples() const
+ { return getCdAlias()->hasExamples(); }
+ virtual QCString getMemberListFileName() const
+ { return getCdAlias()->getMemberListFileName(); }
+ virtual bool subGrouping() const
+ { return getCdAlias()->subGrouping(); }
+ virtual bool isSliceLocal() const
+ { return getCdAlias()->isSliceLocal(); }
+ virtual bool hasNonReferenceSuperClass() const
+ { return getCdAlias()->hasNonReferenceSuperClass(); }
+ virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
+ const QCString &templSpec,bool &freshInstance) const
+ { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); }
+
+ virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) { }
+ virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) { }
+ virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) {}
+ virtual void insertMember(MemberDef *) {}
+ virtual void insertUsedFile(FileDef *) {}
+ virtual bool addExample(const char *anchor,const char *name, const char *file) { return FALSE; }
+ virtual void mergeCategory(ClassDef *category) {}
+ virtual void setNamespace(NamespaceDef *nd) {}
+ virtual void setFileDef(FileDef *fd) {}
+ virtual void setSubGrouping(bool enabled) {}
+ virtual void setProtection(Protection p) {}
+ virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) {}
+ virtual void addInnerCompound(const Definition *d) {}
+ virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) {}
+ virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) {}
+ virtual void setIsStatic(bool b) {}
+ virtual void setCompoundType(CompoundType t) {}
+ virtual void setClassName(const char *name) {}
+ virtual void setClassSpecifier(uint64 spec) {}
+ virtual void setTemplateArguments(ArgumentList *al) {}
+ virtual void setTemplateBaseClassNames(QDict<int> *templateNames) {}
+ virtual void setTemplateMaster(const ClassDef *tm) {}
+ virtual void setTypeConstraints(ArgumentList *al) {}
+ virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) {}
+ virtual void makeTemplateArgument(bool b=TRUE) {}
+ virtual void setCategoryOf(ClassDef *cd) {}
+ virtual void setUsedOnly(bool b) {}
+ virtual void addTaggedInnerClass(ClassDef *cd) {}
+ virtual void setTagLessReference(ClassDef *cd) {}
+ virtual void setName(const char *name) {}
+ virtual void setMetaData(const char *md) {}
+ virtual void findSectionsInDocumentation() {}
+ virtual void addMembersToMemberGroup() {}
+ virtual void addListReferences() {}
+ virtual void addTypeConstraints() {}
+ virtual void computeAnchors() {}
+ virtual void mergeMembers() {}
+ virtual void sortMemberLists() {}
+ virtual void distributeMemberGroupDocumentation() {}
+ virtual void writeDocumentation(OutputList &ol) const {}
+ virtual void writeDocumentationForInnerClasses(OutputList &ol) const {}
+ virtual void writeMemberPages(OutputList &ol) const {}
+ virtual void writeMemberList(OutputList &ol) const {}
+ virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,
+ const ClassDef *inheritedFrom,const char *inheritId) const {}
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const {}
+ virtual void writeSummaryLinks(OutputList &ol) const {}
+ virtual void reclassifyMember(MemberDef *md,MemberType t) {}
+ virtual void writeInlineDocumentation(OutputList &ol) const {}
+ virtual void writeDeclarationLink(OutputList &ol,bool &found,
+ const char *header,bool localNames) const
+ { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); }
+ virtual void removeMemberFromLists(MemberDef *md) {}
+ virtual void setAnonymousEnumType() {}
+ virtual void countMembers() {}
+ virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
+ const ClassDef *inheritedFrom,const QCString &inheritId) const {}
+ virtual void writeTagFile(FTextStream &) {}
+
+ virtual void setVisited(bool visited) const { m_visited = visited; }
+ virtual bool isVisited() const { return m_visited; }
+ virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const
+ { return getCdAlias()->countMembersIncludingGrouped(lt,inheritedFrom,additional); }
+ virtual int countInheritanceNodes() const
+ { return getCdAlias()->countInheritanceNodes(); }
+ virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
+ int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const
+ { return getCdAlias()->countMemberDeclarations(lt,inheritedFrom,lt2,invert,showAlways,visitedClasses); }
+ virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title,
+ const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0,
+ int lt2=-1,bool invert=FALSE,bool showAlways=FALSE,
+ QPtrDict<void> *visitedClasses=0) const {}
+
+ private:
+ mutable bool m_visited;
+};
+
+
+ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd)
+{
+ return new ClassDefAliasImpl(newScope,cd);
+}
+
+//-----------------------------------------------------------------------------
/** Private data associated with a ClassDef object. */
class ClassDefImpl::IMPL
@@ -353,18 +621,18 @@ class ClassDefImpl::IMPL
/*! Template instances that exists of this class, the key in the
* dictionary is the template argument list.
*/
- QDict<ClassDef> *templateInstances;
+ mutable QDict<ClassDef> *templateInstances;
/*! Template instances that exists of this class, as defined by variables.
* We do NOT want to document these individually. The key in the
* dictionary is the template argument list.
*/
- QDict<ClassDef> *variableInstances;
+ mutable QDict<ClassDef> *variableInstances;
QDict<int> *templBaseClassNames;
/*! The class this class is an instance of. */
- ClassDef *templateMaster;
+ const ClassDef *templateMaster;
/*! local class name which could be a typedef'ed alias name. */
QCString className;
@@ -1107,7 +1375,7 @@ void ClassDefImpl::setIncludeFile(FileDef *fd,
// return 0;
//}
-static void searchTemplateSpecs(/*in*/ Definition *d,
+static void searchTemplateSpecs(/*in*/ const Definition *d,
/*out*/ QList<ArgumentList> &result,
/*out*/ QCString &name,
/*in*/ SrcLangExt lang)
@@ -1118,7 +1386,7 @@ static void searchTemplateSpecs(/*in*/ Definition *d,
{
searchTemplateSpecs(d->getOuterScope(),result,name,lang);
}
- ClassDef *cd=dynamic_cast<ClassDef *>(d);
+ const ClassDef *cd=dynamic_cast<const ClassDef *>(d);
if (!name.isEmpty()) name+="::";
QCString clName = d->localName();
if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p")
@@ -1142,7 +1410,7 @@ static void searchTemplateSpecs(/*in*/ Definition *d,
}
}
-static void writeTemplateSpec(OutputList &ol,Definition *d,
+static void writeTemplateSpec(OutputList &ol,const Definition *d,
const QCString &type,SrcLangExt lang)
{
QList<ArgumentList> specs;
@@ -1184,7 +1452,7 @@ static void writeTemplateSpec(OutputList &ol,Definition *d,
}
}
-void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag)
+void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) const
{
if (hasBriefDescription())
{
@@ -1211,7 +1479,7 @@ void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag)
ol.writeSynopsis();
}
-void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol)
+void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const
{
static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
@@ -1270,7 +1538,7 @@ bool ClassDefImpl::hasDetailedDescription() const
// write the detailed description for this class
void ClassDefImpl::writeDetailedDescription(OutputList &ol, const QCString &/*pageType*/, bool exampleFlag,
- const QCString &title,const QCString &anchor)
+ const QCString &title,const QCString &anchor) const
{
if (hasDetailedDescription() || exampleFlag)
{
@@ -1336,7 +1604,7 @@ QCString ClassDefImpl::generatedFromFiles() const
return result;
}
-void ClassDefImpl::showUsedFiles(OutputList &ol)
+void ClassDefImpl::showUsedFiles(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Man);
@@ -1416,7 +1684,7 @@ void ClassDefImpl::showUsedFiles(OutputList &ol)
ol.popGeneratorState();
}
-int ClassDefImpl::countInheritanceNodes()
+int ClassDefImpl::countInheritanceNodes() const
{
int count=0;
BaseClassDef *ibcd;
@@ -1441,7 +1709,7 @@ int ClassDefImpl::countInheritanceNodes()
return count;
}
-void ClassDefImpl::writeInheritanceGraph(OutputList &ol)
+void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const
{
// count direct inheritance relations
const int count=countInheritanceNodes();
@@ -1451,8 +1719,12 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol)
(Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH)))
// write class diagram using dot
{
- DotClassGraph inheritanceGraph(this,DotNode::Inheritance);
- if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig())
+ DotClassGraph inheritanceGraph(this,Inheritance);
+ if (inheritanceGraph.isTooBig())
+ {
+ warn_uncond("Inheritance graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
+ }
+ else if (!inheritanceGraph.isTrivial())
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Man);
@@ -1566,11 +1838,11 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol)
}
}
-void ClassDefImpl::writeCollaborationGraph(OutputList &ol)
+void ClassDefImpl::writeCollaborationGraph(OutputList &ol) const
{
if (Config_getBool(HAVE_DOT) /*&& Config_getBool(COLLABORATION_GRAPH)*/)
{
- DotClassGraph usageImplGraph(this,DotNode::Collaboration);
+ DotClassGraph usageImplGraph(this,Collaboration);
if (!usageImplGraph.isTrivial())
{
ol.pushGeneratorState();
@@ -1601,7 +1873,7 @@ QCString ClassDefImpl::includeStatement() const
}
}
-void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol)
+void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const
{
if (m_impl->incInfo)
{
@@ -1755,7 +2027,7 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol)
ol.endParagraph();
}
-void ClassDefImpl::writeIncludeFiles(OutputList &ol)
+void ClassDefImpl::writeIncludeFiles(OutputList &ol) const
{
if (m_impl->incInfo /*&& Config_getBool(SHOW_INCLUDE_FILES)*/)
{
@@ -1822,7 +2094,7 @@ void ClassDefImpl::writeAllMembersLink(OutputList &ol)
}
#endif
-void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline)
+void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) const
{
// write user defined member groups
if (m_impl->memberGroupSDict)
@@ -1845,7 +2117,7 @@ void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline)
}
}
-void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title)
+void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) const
{
// nested classes
if (m_impl->innerClasses)
@@ -1854,7 +2126,7 @@ void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title)
}
}
-void ClassDefImpl::writeInlineClasses(OutputList &ol)
+void ClassDefImpl::writeInlineClasses(OutputList &ol) const
{
if (m_impl->innerClasses)
{
@@ -1862,7 +2134,7 @@ void ClassDefImpl::writeInlineClasses(OutputList &ol)
}
}
-void ClassDefImpl::startMemberDocumentation(OutputList &ol)
+void ClassDefImpl::startMemberDocumentation(OutputList &ol) const
{
//printf("%s: ClassDefImpl::startMemberDocumentation()\n",name().data());
if (Config_getBool(SEPARATE_MEMBER_PAGES))
@@ -1872,7 +2144,7 @@ void ClassDefImpl::startMemberDocumentation(OutputList &ol)
}
}
-void ClassDefImpl::endMemberDocumentation(OutputList &ol)
+void ClassDefImpl::endMemberDocumentation(OutputList &ol) const
{
//printf("%s: ClassDefImpl::endMemberDocumentation()\n",name().data());
if (Config_getBool(SEPARATE_MEMBER_PAGES))
@@ -1882,13 +2154,13 @@ void ClassDefImpl::endMemberDocumentation(OutputList &ol)
}
}
-void ClassDefImpl::startMemberDeclarations(OutputList &ol)
+void ClassDefImpl::startMemberDeclarations(OutputList &ol) const
{
//printf("%s: ClassDefImpl::startMemberDeclarations()\n",name().data());
ol.startMemberSections();
}
-void ClassDefImpl::endMemberDeclarations(OutputList &ol)
+void ClassDefImpl::endMemberDeclarations(OutputList &ol) const
{
//printf("%s: ClassDefImpl::endMemberDeclarations()\n",name().data());
static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
@@ -1902,7 +2174,7 @@ void ClassDefImpl::endMemberDeclarations(OutputList &ol)
ol.endMemberSections();
}
-void ClassDefImpl::writeAuthorSection(OutputList &ol)
+void ClassDefImpl::writeAuthorSection(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Man);
@@ -1915,7 +2187,7 @@ void ClassDefImpl::writeAuthorSection(OutputList &ol)
}
-void ClassDefImpl::writeSummaryLinks(OutputList &ol)
+void ClassDefImpl::writeSummaryLinks(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
@@ -2093,7 +2365,7 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile)
}
/** Write class documentation inside another container (i.e. a group) */
-void ClassDefImpl::writeInlineDocumentation(OutputList &ol)
+void ClassDefImpl::writeInlineDocumentation(OutputList &ol) const
{
bool isSimple = m_impl->isSimple;
@@ -2210,7 +2482,7 @@ void ClassDefImpl::writeInlineDocumentation(OutputList &ol)
ol.popGeneratorState();
}
-void ClassDefImpl::writeMoreLink(OutputList &ol,const QCString &anchor)
+void ClassDefImpl::writeMoreLink(OutputList &ol,const QCString &anchor) const
{
// TODO: clean up this mess by moving it to
// the output generators...
@@ -2266,7 +2538,7 @@ bool ClassDefImpl::visibleInParentsDeclList() const
);
}
-void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames)
+void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) const
{
//static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
//static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
@@ -2375,7 +2647,7 @@ void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *h
}
}
-void ClassDefImpl::addClassAttributes(OutputList &ol)
+void ClassDefImpl::addClassAttributes(OutputList &ol) const
{
QStrList sl;
if (isFinal()) sl.append("final");
@@ -2400,7 +2672,7 @@ void ClassDefImpl::addClassAttributes(OutputList &ol)
ol.popGeneratorState();
}
-void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/)
+void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/) const
{
ol.startContents();
@@ -2585,7 +2857,7 @@ QCString ClassDefImpl::title() const
}
// write all documentation for this class
-void ClassDefImpl::writeDocumentation(OutputList &ol)
+void ClassDefImpl::writeDocumentation(OutputList &ol) const
{
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
//static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
@@ -2643,7 +2915,7 @@ void ClassDefImpl::writeDocumentation(OutputList &ol)
}
}
-void ClassDefImpl::writeMemberPages(OutputList &ol)
+void ClassDefImpl::writeMemberPages(OutputList &ol) const
{
///////////////////////////////////////////////////////////////////////////
//// Member definitions on separate pages
@@ -2656,8 +2928,7 @@ void ClassDefImpl::writeMemberPages(OutputList &ol)
MemberList *ml;
for (mli.toFirst();(ml=mli.current());++mli)
{
- ml->countDocMembers();
- if (ml->numDocMembers()>0 && (ml->listType()&MemberListType_detailedLists))
+ if (ml->numDocMembers()>ml->numDocEnumValues() && (ml->listType()&MemberListType_detailedLists))
{
ml->writeDocumentationPage(ol,displayName(),this);
}
@@ -2666,7 +2937,7 @@ void ClassDefImpl::writeMemberPages(OutputList &ol)
ol.popGeneratorState();
}
-void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
+void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const
{
static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
@@ -2716,7 +2987,7 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) co
-void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol)
+void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const
{
// write inner classes after the parent, so the tag files contain
// the definition in proper order!
@@ -2741,7 +3012,7 @@ void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol)
}
// write the list of all (inherited) members for this class
-void ClassDefImpl::writeMemberList(OutputList &ol)
+void ClassDefImpl::writeMemberList(OutputList &ol) const
{
static bool cOpt = Config_getBool(OPTIMIZE_OUTPUT_FOR_C);
//static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
@@ -2811,7 +3082,7 @@ void ClassDefImpl::writeMemberList(OutputList &ol)
for (;(mi=it.current());++it)
{
MemberDef *md=mi->memberDef;
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
Protection prot = mi->prot;
Specifier virt=md->virtualness();
@@ -3024,7 +3295,6 @@ void ClassDefImpl::writeMemberList(OutputList &ol)
ol.popGeneratorState();
}
-
// add a reference to an example
bool ClassDefImpl::addExample(const char *anchor,const char *nameStr,
const char *file)
@@ -3060,7 +3330,7 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri
//printf("addTypeContraint(%s,%s)\n",type.data(),typeConstraint.data());
static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS);
if (typeConstraint.isEmpty() || type.isEmpty()) return;
- ClassDef *cd = getResolvedClass(this,getFileDef(),typeConstraint);
+ ClassDef *cd = const_cast<ClassDef*>(getResolvedClass(this,getFileDef(),typeConstraint));
if (cd==0 && !hideUndocRelation)
{
cd = new ClassDefImpl(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class);
@@ -3183,8 +3453,8 @@ bool ClassDefImpl::hasNonReferenceSuperClass() const
/*! called from MemberDef::writeDeclaration() to (recursively) write the
* definition of an anonymous struct, union or class.
*/
-void ClassDefImpl::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup,
- ClassDef *inheritedFrom,const char *inheritId)
+void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,
+ const ClassDef *inheritedFrom,const char *inheritId) const
{
//printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup);
@@ -3319,7 +3589,7 @@ bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int lev
BaseClassListIterator bcli(*baseClasses());
for ( ; bcli.current() && !found ; ++bcli)
{
- ClassDef *ccd=bcli.current()->classDef;
+ const ClassDef *ccd=bcli.current()->classDef;
if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
//printf("isBaseClass() baseclass %s\n",ccd->name().data());
if (ccd==bcd)
@@ -3382,7 +3652,8 @@ void ClassDefImpl::mergeMembers()
m_impl->membersMerged=TRUE;
//printf(" mergeMembers for %s\n",name().data());
- bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
+ static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB);
+ static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
if (baseClasses())
{
//printf(" => has base classes!\n");
@@ -3422,19 +3693,19 @@ void ClassDefImpl::mergeMembers()
bool hidden=FALSE;
MemberNameInfoIterator dstMnii(*dstMni);
MemberInfo *dstMi;
- ClassDef *srcCd = srcMd->getClassDef();
+ const ClassDef *srcCd = srcMd->getClassDef();
for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
{
MemberDef *dstMd = dstMi->memberDef;
if (srcMd!=dstMd) // different members
{
- ClassDef *dstCd = dstMd->getClassDef();
+ const ClassDef *dstCd = dstMd->getClassDef();
//printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data());
if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE))
// member is in the same or a base class
{
- ArgumentList *srcAl = srcMd->argumentList();
- ArgumentList *dstAl = dstMd->argumentList();
+ const ArgumentList *srcAl = srcMd->argumentList();
+ const ArgumentList *dstAl = dstMd->argumentList();
found=matchArguments2(
srcMd->getOuterScope(),srcMd->getFileDef(),srcAl,
dstMd->getOuterScope(),dstMd->getFileDef(),dstAl,
@@ -3578,7 +3849,7 @@ void ClassDefImpl::mergeMembers()
// name().data(),mi->memberDef->name().data(),mi->prot,
// bcd->prot,prot);
- if (mi->prot!=Private)
+ if (prot!=Private || extractPrivate)
{
Specifier virt=mi->virt;
if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
@@ -4135,7 +4406,7 @@ void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pr
}
}
-void ClassDefImpl::addInnerCompound(Definition *d)
+void ClassDefImpl::addInnerCompound(const Definition *d)
{
//printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data());
if (d->definitionType()==Definition::TypeClass) // only classes can be
@@ -4145,7 +4416,7 @@ void ClassDefImpl::addInnerCompound(Definition *d)
{
m_impl->innerClasses = new ClassSDict(17);
}
- m_impl->innerClasses->inSort(d->localName(),dynamic_cast<ClassDef *>(d));
+ m_impl->innerClasses->inSort(d->localName(),dynamic_cast<const ClassDef *>(d));
}
}
@@ -4201,7 +4472,7 @@ Definition *ClassDefImpl::findInnerCompound(const char *name) const
//}
ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName,
- int startLine, int startColumn, const QCString &templSpec,bool &freshInstance)
+ int startLine, int startColumn, const QCString &templSpec,bool &freshInstance) const
{
freshInstance = FALSE;
if (m_impl->templateInstances==0)
@@ -4224,7 +4495,7 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName,
return templateClass;
}
-ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec)
+ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec) const
{
if (m_impl->variableInstances==0)
{
@@ -4269,7 +4540,7 @@ QDict<int> *ClassDefImpl::getTemplateBaseClassNames() const
return m_impl->templBaseClassNames;
}
-void ClassDefImpl::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec)
+void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec)
{
//printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec);
if (cd->memberNameInfoSDict()==0) return;
@@ -4480,7 +4751,7 @@ MemberDef *ClassDefImpl::getMemberByName(const QCString &name) const
MemberInfo *mi;
for (mnii.toFirst();(mi=mnii.current());++mnii)
{
- ClassDef *mcd=mi->memberDef->getClassDef();
+ const ClassDef *mcd=mi->memberDef->getClassDef();
int m=minClassDistance(this,mcd);
//printf("found member in %s linkable=%d m=%d\n",
// mcd->name().data(),mcd->isLinkable(),m);
@@ -4559,8 +4830,8 @@ void ClassDefImpl::sortMemberLists()
}
}
-int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom,
- int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses)
+int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
+ int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const
{
//printf("%s: countMemberDeclarations for %d and %d\n",name().data(),lt,lt2);
int count=0;
@@ -4570,13 +4841,11 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedF
{
if (ml)
{
- ml->countDecMembers();
count+=ml->numDecMembers();
//printf("-> ml=%d\n",ml->numDecMembers());
}
if (ml2)
{
- ml2->countDecMembers();
count+=ml2->numDecMembers();
//printf("-> ml2=%d\n",ml2->numDecMembers());
}
@@ -4601,10 +4870,61 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedF
return count;
}
+void ClassDefImpl::setAnonymousEnumType()
+{
+ QListIterator<LayoutDocEntry> eli(
+ LayoutDocManager::instance().docEntries(LayoutDocManager::Class));
+ LayoutDocEntry *lde;
+ for (eli.toFirst();(lde=eli.current());++eli)
+ {
+ if (lde->kind()==LayoutDocEntry::MemberDecl)
+ {
+ LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde;
+ MemberList * ml = getMemberList(lmd->type);
+ if (ml)
+ {
+ ml->setAnonymousEnumType();
+ }
+ }
+ else if (lde->kind()==LayoutDocEntry::MemberGroups)
+ {
+ if (m_impl->memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->setAnonymousEnumType();
+ }
+ }
+ }
+ }
+}
+
+void ClassDefImpl::countMembers()
+{
+ QListIterator<MemberList> mli(m_impl->memberLists);
+ MemberList *ml;
+ for (mli.toFirst();(ml=mli.current());++mli)
+ {
+ ml->countDecMembers();
+ ml->countDocMembers();
+ }
+ if (m_impl->memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->countDecMembers();
+ mg->countDocMembers();
+ }
+ }
+}
int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
- ClassDef *inheritedFrom,bool invert,bool showAlways,
- QPtrDict<void> *visitedClasses)
+ const ClassDef *inheritedFrom,bool invert,bool showAlways,
+ QPtrDict<void> *visitedClasses) const
{
int inhCount = 0;
int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE);
@@ -4642,7 +4962,7 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt,
}
void ClassDefImpl::getTitleForMemberListType(MemberListType type,
- QCString &title,QCString &subtitle)
+ QCString &title,QCString &subtitle) const
{
SrcLangExt lang = getLanguage();
QListIterator<LayoutDocEntry> eli(
@@ -4665,7 +4985,7 @@ void ClassDefImpl::getTitleForMemberListType(MemberListType type,
subtitle="";
}
-int ClassDefImpl::countAdditionalInheritedMembers()
+int ClassDefImpl::countAdditionalInheritedMembers() const
{
int totalCount=0;
QListIterator<LayoutDocEntry> eli(
@@ -4691,7 +5011,7 @@ int ClassDefImpl::countAdditionalInheritedMembers()
return totalCount;
}
-void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol)
+void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol) const
{
//printf("**** writeAdditionalInheritedMembers()\n");
QListIterator<LayoutDocEntry> eli(
@@ -4712,7 +5032,7 @@ void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol)
}
int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt,
- ClassDef *inheritedFrom,bool additional)
+ const ClassDef *inheritedFrom,bool additional) const
{
int count=0;
MemberList *ml = getMemberList(lt);
@@ -4740,10 +5060,11 @@ int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt,
return count;
}
+
void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol,
MemberListType lt,int lt2,const QCString &title,
- ClassDef *inheritedFrom,bool invert,bool showAlways,
- QPtrDict<void> *visitedClasses)
+ const ClassDef *inheritedFrom,bool invert,bool showAlways,
+ QPtrDict<void> *visitedClasses) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
@@ -4790,15 +5111,15 @@ void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol,
}
void ClassDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title,
- const char *subTitle,bool showInline,ClassDef *inheritedFrom,int lt2,
- bool invert,bool showAlways,QPtrDict<void> *visitedClasses)
+ const char *subTitle,bool showInline,const ClassDef *inheritedFrom,int lt2,
+ bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const
{
//printf("%s: ClassDefImpl::writeMemberDeclarations lt=%d lt2=%d\n",name().data(),lt,lt2);
MemberList * ml = getMemberList(lt);
MemberList * ml2 = getMemberList((MemberListType)lt2);
if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function
{
- static ClassDef *cdef;
+ static const ClassDef *cdef;
if (cdef!=this)
{ // only one inline link
VhdlDocGen::writeInlineClassLink(this,ol);
@@ -4838,7 +5159,7 @@ void ClassDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,cons
}
void ClassDefImpl::addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
- ClassDef *inheritedFrom,const QCString &inheritId)
+ const ClassDef *inheritedFrom,const QCString &inheritId) const
{
//printf("** %s::addGroupedInheritedMembers(%p) inheritId=%s\n",name().data(),m_impl->memberGroupSDict,inheritId.data());
if (m_impl->memberGroupSDict)
@@ -4855,14 +5176,14 @@ void ClassDefImpl::addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
}
}
-void ClassDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline)
+void ClassDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline) const
{
//printf("%s: ClassDefImpl::writeMemberDocumentation()\n",name().data());
MemberList * ml = getMemberList(lt);
if (ml) ml->writeDocumentation(ol,displayName(),this,title,FALSE,showInline);
}
-void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt)
+void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const
{
//printf("%s: ClassDefImpl::writeSimpleMemberDocumentation()\n",name().data());
MemberList * ml = getMemberList(lt);
@@ -4871,7 +5192,7 @@ void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType
void ClassDefImpl::writePlainMemberDeclaration(OutputList &ol,
MemberListType lt,bool inGroup,
- ClassDef *inheritedFrom,const char *inheritId)
+ const ClassDef *inheritedFrom,const char *inheritId) const
{
//printf("%s: ClassDefImpl::writePlainMemberDeclaration()\n",name().data());
MemberList * ml = getMemberList(lt);
@@ -4937,7 +5258,7 @@ QDict<ClassDef> *ClassDefImpl::getTemplateInstances() const
return m_impl->templateInstances;
}
-ClassDef *ClassDefImpl::templateMaster() const
+const ClassDef *ClassDefImpl::templateMaster() const
{
return m_impl->templateMaster;
}
@@ -5067,7 +5388,7 @@ void ClassDefImpl::setCompoundType(CompoundType t)
m_impl->compType = t;
}
-void ClassDefImpl::setTemplateMaster(ClassDef *tm)
+void ClassDefImpl::setTemplateMaster(const ClassDef *tm)
{
m_impl->templateMaster=tm;
}
diff --git a/src/classdef.h b/src/classdef.h
index 58a3dee..a442ace 100644
--- a/src/classdef.h
+++ b/src/classdef.h
@@ -72,6 +72,8 @@ class ClassDef : virtual public Definition
virtual ~ClassDef() {}
+ virtual ClassDef *resolveAlias() = 0;
+
//-----------------------------------------------------------------------------------
// --- getters
//-----------------------------------------------------------------------------------
@@ -197,7 +199,7 @@ class ClassDef : virtual public Definition
/** Returns the template master of which this class is an instance.
* Returns 0 if not applicable.
*/
- virtual ClassDef *templateMaster() const = 0;
+ virtual const ClassDef *templateMaster() const = 0;
/** Returns TRUE if this class is a template */
virtual bool isTemplate() const = 0;
@@ -283,7 +285,7 @@ class ClassDef : virtual public Definition
virtual QDict<int> *getTemplateBaseClassNames() const = 0;
- virtual ClassDef *getVariableInstance(const char *templSpec) = 0;
+ virtual ClassDef *getVariableInstance(const char *templSpec) const = 0;
virtual bool isUsedOnly() const = 0;
@@ -314,52 +316,50 @@ class ClassDef : virtual public Definition
virtual bool subGrouping() const = 0;
virtual bool isSliceLocal() const = 0;
+ virtual bool hasNonReferenceSuperClass() const = 0;
//-----------------------------------------------------------------------------------
// --- setters ----
//-----------------------------------------------------------------------------------
- virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) = 0;
- virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) = 0;
virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) = 0;
- virtual void insertMember(MemberDef *) = 0;
- virtual void insertUsedFile(FileDef *) = 0;
- virtual bool addExample(const char *anchor,const char *name, const char *file) = 0;
- virtual void mergeCategory(ClassDef *category) = 0;
virtual void setNamespace(NamespaceDef *nd) = 0;
virtual void setFileDef(FileDef *fd) = 0;
virtual void setSubGrouping(bool enabled) = 0;
virtual void setProtection(Protection p) = 0;
virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) = 0;
- virtual void addInnerCompound(Definition *d) = 0;
- virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
- const QCString &templSpec,bool &freshInstance) = 0;
- virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) = 0;
- virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) = 0;
virtual void setIsStatic(bool b) = 0;
virtual void setCompoundType(CompoundType t) = 0;
virtual void setClassName(const char *name) = 0;
virtual void setClassSpecifier(uint64 spec) = 0;
-
virtual void setTemplateArguments(ArgumentList *al) = 0;
virtual void setTemplateBaseClassNames(QDict<int> *templateNames) = 0;
- virtual void setTemplateMaster(ClassDef *tm) = 0;
+ virtual void setTemplateMaster(const ClassDef *tm) = 0;
virtual void setTypeConstraints(ArgumentList *al) = 0;
- virtual void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) = 0;
- virtual void makeTemplateArgument(bool b=TRUE) = 0;
virtual void setCategoryOf(ClassDef *cd) = 0;
virtual void setUsedOnly(bool b) = 0;
-
- virtual void addTaggedInnerClass(ClassDef *cd) = 0;
virtual void setTagLessReference(ClassDef *cd) = 0;
virtual void setName(const char *name) = 0;
-
virtual void setMetaData(const char *md) = 0;
//-----------------------------------------------------------------------------------
// --- actions ----
//-----------------------------------------------------------------------------------
+ virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) = 0;
+ virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) = 0;
+ virtual void insertMember(MemberDef *) = 0;
+ virtual void insertUsedFile(FileDef *) = 0;
+ virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) = 0;
+ virtual void addTaggedInnerClass(ClassDef *cd) = 0;
+ virtual void addInnerCompound(const Definition *d) = 0;
+ virtual bool addExample(const char *anchor,const char *name, const char *file) = 0;
+ virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn,
+ const QCString &templSpec,bool &freshInstance) const = 0;
+ virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) = 0;
+ virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) = 0;
+ virtual void makeTemplateArgument(bool b=TRUE) = 0;
+ virtual void mergeCategory(ClassDef *category) = 0;
virtual void findSectionsInDocumentation() = 0;
virtual void addMembersToMemberGroup() = 0;
virtual void addListReferences() = 0;
@@ -368,34 +368,51 @@ class ClassDef : virtual public Definition
virtual void mergeMembers() = 0;
virtual void sortMemberLists() = 0;
virtual void distributeMemberGroupDocumentation() = 0;
- virtual void writeDocumentation(OutputList &ol) = 0;
- virtual void writeDocumentationForInnerClasses(OutputList &ol) = 0;
- virtual void writeMemberPages(OutputList &ol) = 0;
- virtual void writeMemberList(OutputList &ol) = 0;
- virtual void writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup,
- ClassDef *inheritedFrom,const char *inheritId) = 0;
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *md) const = 0;
- virtual void writeSummaryLinks(OutputList &ol) = 0;
virtual void reclassifyMember(MemberDef *md,MemberType t) = 0;
- virtual void writeInlineDocumentation(OutputList &ol) = 0;
- virtual void writeDeclarationLink(OutputList &ol,bool &found,
- const char *header,bool localNames) = 0;
virtual void removeMemberFromLists(MemberDef *md) = 0;
- virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
- ClassDef *inheritedFrom,const QCString &inheritId) = 0;
- virtual int countMembersIncludingGrouped(MemberListType lt,ClassDef *inheritedFrom,bool additional) = 0;
- virtual int countInheritanceNodes() = 0;
- virtual void writeTagFile(FTextStream &) = 0;
+ virtual void setAnonymousEnumType() = 0;
+ virtual void countMembers() = 0;
- virtual void setVisited(bool visited) = 0;
- virtual bool isVisited() const = 0;
- virtual bool hasNonReferenceSuperClass() const = 0;
- virtual int countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom,
- int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) = 0;
+ //-----------------------------------------------------------------------------------
+ // --- write output ----
+ //-----------------------------------------------------------------------------------
+
+ virtual void writeDocumentation(OutputList &ol) const = 0;
+ virtual void writeDocumentationForInnerClasses(OutputList &ol) const = 0;
+ virtual void writeMemberPages(OutputList &ol) const = 0;
+ virtual void writeMemberList(OutputList &ol) const = 0;
+ virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup,
+ const ClassDef *inheritedFrom,const char *inheritId) const = 0;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const = 0;
+ virtual void writeSummaryLinks(OutputList &ol) const = 0;
+ virtual void writeInlineDocumentation(OutputList &ol) const = 0;
+ virtual void writeDeclarationLink(OutputList &ol,bool &found,
+ const char *header,bool localNames) const = 0;
+ virtual void writeTagFile(FTextStream &) = 0;
virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title,
- const char *subTitle=0,bool showInline=FALSE,ClassDef *inheritedFrom=0,
+ const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0,
int lt2=-1,bool invert=FALSE,bool showAlways=FALSE,
- QPtrDict<void> *visitedClasses=0) = 0;
+ QPtrDict<void> *visitedClasses=0) const = 0;
+ virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt,
+ const ClassDef *inheritedFrom,const QCString &inheritId) const = 0;
+
+ //-----------------------------------------------------------------------------------
+ // --- count members ----
+ //-----------------------------------------------------------------------------------
+
+ virtual int countMembersIncludingGrouped(MemberListType lt,
+ const ClassDef *inheritedFrom,bool additional) const = 0;
+ virtual int countInheritanceNodes() const = 0;
+ virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom,
+ int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const = 0;
+
+
+ //-----------------------------------------------------------------------------------
+ // --- visiting administration ----
+ //-----------------------------------------------------------------------------------
+
+ virtual void setVisited(bool visited) const = 0;
+ virtual bool isVisited() const = 0;
};
/** Factory method to create a new ClassDef object */
@@ -405,6 +422,9 @@ ClassDef *createClassDef(
const char *ref=0,const char *fName=0,
bool isSymbol=TRUE,bool isJavaEnum=FALSE);
+ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd);
+
+
//------------------------------------------------------------------------
/** Class that contains information about a usage relation.
diff --git a/src/classlist.cpp b/src/classlist.cpp
index c752fd3..93ae8aa 100644
--- a/src/classlist.cpp
+++ b/src/classlist.cpp
@@ -92,7 +92,7 @@ bool ClassSDict::declVisible(const ClassDef::CompoundType *filter) const
}
void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter,
- const char *header,bool localNames)
+ const char *header,bool localNames) const
{
static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
if (count()>0)
@@ -109,6 +109,7 @@ void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *f
(filter==0 || *filter==cd->compoundType())
)
{
+ //printf("writeDeclarationLink()\n");
cd->writeDeclarationLink(ol,found,header,localNames);
}
}
@@ -116,7 +117,7 @@ void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *f
}
}
-void ClassSDict::writeDocumentation(OutputList &ol,Definition * container)
+void ClassSDict::writeDocumentation(OutputList &ol,const Definition * container) const
{
static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
@@ -139,6 +140,7 @@ void ClassSDict::writeDocumentation(OutputList &ol,Definition * container)
if (cd->name().find('@')==-1 &&
cd->isLinkableInProject() &&
cd->isEmbeddedInOuterScope() &&
+ !cd->isAlias() &&
(container==0 || cd->partOfGroups()==0) // if container==0 -> show as part of the group docs, otherwise only show if not part of a group
)
{
diff --git a/src/classlist.h b/src/classlist.h
index 2ae7de8..11c8305 100644
--- a/src/classlist.h
+++ b/src/classlist.h
@@ -59,8 +59,8 @@ class ClassSDict : public SDict<ClassDef>
ClassSDict(int size=17) : SDict<ClassDef>(size) {}
~ClassSDict() {}
void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter=0,
- const char *header=0,bool localNames=FALSE);
- void writeDocumentation(OutputList &ol,Definition *container=0);
+ const char *header=0,bool localNames=FALSE) const;
+ void writeDocumentation(OutputList &ol,const Definition *container=0) const;
bool declVisible(const ClassDef::CompoundType *filter=0) const;
private:
int compareValues(const ClassDef *item1,const ClassDef *item2) const;
diff --git a/src/code.h b/src/code.h
index 1b4c0ac..da6b80e 100644
--- a/src/code.h
+++ b/src/code.h
@@ -29,7 +29,7 @@ class Definition;
void parseCCode(CodeOutputInterface &,const char *,const QCString &,
SrcLangExt lang, bool isExample, const char *exName,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs);
void resetCCodeParserState();
void codeFreeScanner();
diff --git a/src/code.l b/src/code.l
index b2dacba..ad9447b 100644
--- a/src/code.l
+++ b/src/code.l
@@ -129,7 +129,7 @@ static bool g_lexInit = FALSE;
static QStack<int> g_classScopeLengthStack;
static int g_prefixed_with_this_keyword = FALSE;
-static Definition *g_searchCtx;
+static const Definition *g_searchCtx;
static bool g_collectXRefs;
// context for an Objective-C method call
@@ -139,9 +139,9 @@ struct ObjCCallCtx
QCString methodName;
QCString objectTypeOrName;
QGString comment;
- ClassDef *objectType;
- MemberDef *objectVar;
- MemberDef *method;
+ const ClassDef *objectType;
+ const MemberDef *objectVar;
+ const MemberDef *method;
QCString format;
int lexState;
int braceCount;
@@ -252,7 +252,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name)
DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n",
ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>"));
Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
- ClassDef *varType;
+ const ClassDef *varType;
int i=0;
if (
(varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block
@@ -338,19 +338,19 @@ class CallContext
public:
struct Ctx
{
- Ctx() : name(g_name), type(g_type), d(0) {}
+ Ctx(QCString _name, QCString _type) : name(_name), type(_type), d(0) {}
QCString name;
QCString type;
- Definition *d;
+ const Definition *d;
};
- CallContext()
+ CallContext()
{
- m_defList.append(new Ctx);
+ m_defList.append(new Ctx("",""));
m_defList.setAutoDelete(TRUE);
}
virtual ~CallContext() {}
- void setScope(Definition *d)
+ void setScope(const Definition *d)
{
Ctx *ctx = m_defList.getLast();
if (ctx)
@@ -359,12 +359,12 @@ class CallContext
ctx->d=d;
}
}
- void pushScope()
+ void pushScope(QCString _name, QCString _type)
{
- m_defList.append(new Ctx);
+ m_defList.append(new Ctx(_name,_type));
DBG_CTX((stderr,"** Push call context %d\n",m_defList.count()));
}
- void popScope()
+ void popScope(QCString &_name, QCString &_type)
{
if (m_defList.count()>1)
{
@@ -372,8 +372,8 @@ class CallContext
Ctx *ctx = m_defList.getLast();
if (ctx)
{
- g_name = ctx->name;
- g_type = ctx->type;
+ _name = ctx->name;
+ _type = ctx->type;
}
m_defList.removeLast();
}
@@ -386,9 +386,9 @@ class CallContext
{
DBG_CTX((stderr,"** Clear call context\n"));
m_defList.clear();
- m_defList.append(new Ctx);
+ m_defList.append(new Ctx("",""));
}
- Definition *getScope() const
+ const Definition *getScope() const
{
Ctx *ctx = m_defList.getLast();
if (ctx) return ctx->d; else return 0;
@@ -606,7 +606,7 @@ static void codifyLines(const char *text)
* split into multiple links with the same destination, one for each line.
*/
static void writeMultiLineCodeLink(CodeOutputInterface &ol,
- Definition *d,
+ const Definition *d,
const char *text)
{
static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
@@ -674,13 +674,13 @@ static void addUsingDirective(const char *name)
}
}
-static void setParameterList(MemberDef *md)
+static void setParameterList(const MemberDef *md)
{
g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
- ArgumentList *al = md->argumentList();
+ const ArgumentList *al = md->argumentList();
if (al==0) return;
ArgumentListIterator it(*al);
- Argument *a;
+ const Argument *a;
for (;(a=it.current());++it)
{
g_parmName = a->name.copy();
@@ -695,7 +695,7 @@ static void setParameterList(MemberDef *md)
}
}
-static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
+static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
{
int pos=0;
QCString type = s;
@@ -704,7 +704,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
while (extractClassNameFromType(type,pos,className,templSpec)!=-1)
{
QCString clName=className+templSpec;
- ClassDef *cd=0;
+ const ClassDef *cd=0;
if (!g_classScope.isEmpty())
{
cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
@@ -747,7 +747,7 @@ static MemberDef *setCallContextForVar(const QCString &name)
}
else // check namespace as well
{
- NamespaceDef *mnd = getResolvedNamespace(scope);
+ const NamespaceDef *mnd = getResolvedNamespace(scope);
if (mnd && !locName.isEmpty())
{
MemberDef *md=mnd->getMemberByName(locName);
@@ -838,12 +838,12 @@ static MemberDef *setCallContextForVar(const QCString &name)
static void updateCallContextForSmartPointer()
{
- Definition *d = g_theCallContext.getScope();
+ const Definition *d = g_theCallContext.getScope();
//printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>");
MemberDef *md;
- if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<ClassDef*>(d))->isSmartPointer()))
+ if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer()))
{
- ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
+ const ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope());
if (ncd)
{
g_theCallContext.setScope(ncd);
@@ -860,11 +860,11 @@ static bool getLinkInScope(const QCString &c, // scope
bool varOnly=FALSE
)
{
- MemberDef *md;
- ClassDef *cd;
- FileDef *fd;
- NamespaceDef *nd;
- GroupDef *gd;
+ const MemberDef *md = 0;
+ const ClassDef *cd = 0;
+ const FileDef *fd = 0;
+ const NamespaceDef *nd = 0;
+ const GroupDef *gd = 0;
DBG_CTX((stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly));
if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) &&
(!varOnly || md->isVariable()))
@@ -878,16 +878,16 @@ static bool getLinkInScope(const QCString &c, // scope
anchor.sprintf("a%d",g_anchorCount);
//printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
// g_exampleFile.data());
- if (md->addExample(anchor,g_exampleName,g_exampleFile))
+ if (const_cast<MemberDef*>(md)->addExample(anchor,g_exampleName,g_exampleFile))
{
ol.writeCodeAnchor(anchor);
g_anchorCount++;
}
}
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getFileDef() : md->getOuterScope();
- if (md->getGroupDef()) d = md->getGroupDef();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->resolveAlias()->getFileDef() : md->getOuterScope();
+ if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef();
if (d && d->isLinkable())
{
g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope()));
@@ -897,7 +897,7 @@ static bool getLinkInScope(const QCString &c, // scope
if (g_currentDefinition && g_currentMemberDef &&
md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,md);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
}
//printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data());
@@ -961,8 +961,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
{
className = substitute(className,".","::"); // for PHP namespaces
}
- ClassDef *cd=0,*lcd=0;
- MemberDef *md=0;
+ const ClassDef *cd=0,*lcd=0;
+ const MemberDef *md=0;
bool isLocal=FALSE;
//printf("generateClassOrGlobalLink(className=%s)\n",className.data());
@@ -983,7 +983,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version
}
}
- NamespaceDef *nd = getResolvedNamespace(className);
+ const NamespaceDef *nd = getResolvedNamespace(className);
if (nd && nd->isLinkableInProject())
{
g_theCallContext.setScope(nd);
@@ -1033,7 +1033,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
anchor.sprintf("_a%d",g_anchorCount);
//printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(),
// g_exampleFile.data());
- if (cd->addExample(anchor,g_exampleName,g_exampleFile))
+ if (const_cast<ClassDef*>(cd)->addExample(anchor,g_exampleName,g_exampleFile))
{
ol.writeCodeAnchor(anchor);
g_anchorCount++;
@@ -1044,13 +1044,13 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
g_theCallContext.setScope(cd);
if (md)
{
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
md->getFileDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable() && md->isLinkable() &&
g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,md);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
}
}
}
@@ -1092,8 +1092,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
}
text+=getLanguageSpecificSeparator(md->getLanguage());
text+=clName;
- md->setName(text);
- md->setLocalName(text);
+ const_cast<MemberDef*>(md)->setName(text);
+ const_cast<MemberDef*>(md)->setLocalName(text);
}
else // normal reference
{
@@ -1103,7 +1103,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName
addToSearchIndex(clName);
if (g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,md);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
}
return;
}
@@ -1139,11 +1139,11 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const
}
}
- ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
+ const ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope());
DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass));
g_theCallContext.setScope(typeClass);
- Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
+ const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ?
xmd->getFileDef() : xmd->getOuterScope();
if (xmd->getGroupDef()) xd = xmd->getGroupDef();
if (xd && xd->isLinkable())
@@ -1172,11 +1172,11 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const
return FALSE;
}
-static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,const char *memName)
+static bool generateClassMemberLink(CodeOutputInterface &ol,const Definition *def,const char *memName)
{
if (def && def->definitionType()==Definition::TypeClass)
{
- ClassDef *cd = dynamic_cast<ClassDef*>(def);
+ const ClassDef *cd = dynamic_cast<const ClassDef*>(def);
MemberDef *xmd = cd->getMemberByName(memName);
//printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd);
if (xmd)
@@ -1197,7 +1197,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,cons
}
else if (def && def->definitionType()==Definition::TypeNamespace)
{
- NamespaceDef *nd = dynamic_cast<NamespaceDef*>(def);
+ const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(def);
//printf("Looking for %s inside namespace %s\n",memName,nd->name().data());
Definition *innerDef = nd->findInnerCompound(memName);
if (innerDef)
@@ -1220,7 +1220,7 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
if (varName.isEmpty()) return;
// look for the variable in the current context
- ClassDef *vcd = g_theVarContext.findVariable(varName);
+ const ClassDef *vcd = g_theVarContext.findVariable(varName);
if (vcd)
{
if (vcd!=VariableContext::dummyContext)
@@ -1265,14 +1265,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
if (vmn)
{
MemberNameIterator vmni(*vmn);
- MemberDef *vmd;
+ const MemberDef *vmd;
for (;(vmd=vmni.current());++vmni)
{
if (/*(vmd->isVariable() || vmd->isFunction()) && */
vmd->getClassDef()==jcd)
{
//printf("Found variable type=%s\n",vmd->typeString());
- ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
+ const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
if (mcd && mcd->isLinkable())
{
if (generateClassMemberLink(ol,mcd,memName)) return;
@@ -1286,14 +1286,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName,
{
//printf("There is a variable with name `%s'\n",varName);
MemberNameIterator vmni(*vmn);
- MemberDef *vmd;
+ const MemberDef *vmd;
for (;(vmd=vmni.current());++vmni)
{
if (/*(vmd->isVariable() || vmd->isFunction()) && */
vmd->getClassDef()==vcd)
{
//printf("Found variable type=%s\n",vmd->typeString());
- ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
+ const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope());
if (mcd && mcd->isLinkable())
{
if (generateClassMemberLink(ol,mcd,memName)) return;
@@ -1335,7 +1335,7 @@ static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName)
DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data()));
int len=2;
int i=locFunc.findRev("::");
- if (g_currentMemberDef && g_currentMemberDef->getClassDef() &&
+ if (g_currentMemberDef && g_currentMemberDef->resolveAlias()->getClassDef() &&
funcName==g_currentMemberDef->localName() &&
g_currentMemberDef->getDefLine()==g_yyLineNr &&
generateClassMemberLink(ol,g_currentMemberDef,funcName)
@@ -1561,7 +1561,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx)
writeMultiLineCodeLink(*g_code,ctx->method,pName->data());
if (g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,ctx->method);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->method));
}
}
else
@@ -1640,7 +1640,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx)
writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data());
if (g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,ctx->objectVar);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->objectVar));
}
}
else if (ctx->objectType &&
@@ -1648,12 +1648,12 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx)
ctx->objectType->isLinkable()
) // object is class name
{
- ClassDef *cd = ctx->objectType;
+ const ClassDef *cd = ctx->objectType;
writeMultiLineCodeLink(*g_code,cd,pObject->data());
}
else // object still needs to be resolved
{
- ClassDef *cd = getResolvedClass(g_currentDefinition,
+ const ClassDef *cd = getResolvedClass(g_currentDefinition,
g_sourceFileDef, *pObject);
if (cd && cd->isLinkable())
{
@@ -2302,12 +2302,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
char *s=g_curClassBases.first();
while (s)
{
- ClassDef *bcd;
- bcd=g_codeClassSDict->find(s);
+ const ClassDef *bcd=g_codeClassSDict->find(s);
if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s);
if (bcd && bcd!=ncd)
{
- ncd->insertBaseClass(bcd,s,Public,Normal);
+ ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal);
}
s=g_curClassBases.next();
}
@@ -2510,7 +2509,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
}
<Body>"*"{B}*")" { // end of cast?
g_code->codify(yytext);
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
g_bracketCount--;
g_parmType = g_name;
BEGIN(FuncCall);
@@ -2520,7 +2519,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_name.resize(0);g_type.resize(0);
if (*yytext==')')
{
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
g_bracketCount--;
BEGIN(FuncCall);
}
@@ -2852,7 +2851,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
}
else if (*yytext=='[')
{
- g_theCallContext.pushScope();
+ g_theCallContext.pushScope(g_name, g_type);
}
g_args.resize(0);
g_parmType.resize(0);
@@ -2878,7 +2877,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
}
<ObjCMemberCall>"[" {
g_code->codify(yytext);
- g_theCallContext.pushScope();
+ g_theCallContext.pushScope(g_name, g_type);
}
<ObjCMemberCall2>{ID}":"? {
g_name+=yytext;
@@ -2900,7 +2899,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
BEGIN(ObjCMemberCall3);
}
<ObjCMemberCall2,ObjCMemberCall3>"]" {
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
g_code->codify(yytext);
BEGIN(Body);
}
@@ -2990,7 +2989,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
<ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; }
<Body>"]" {
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
g_code->codify(yytext);
// TODO: nested arrays like: a[b[0]->func()]->func()
g_name = g_saveName.copy();
@@ -3093,7 +3092,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_parmType.resize(0);g_parmName.resize(0);
g_code->codify(yytext);
g_bracketCount++;
- g_theCallContext.pushScope();
+ g_theCallContext.pushScope(g_name, g_type);
if (YY_START==FuncCall && !g_insideBody)
{
g_theVarContext.pushScope();
@@ -3127,7 +3126,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_parmName.resize(0);
g_theVarContext.addVariable(g_parmType,g_parmName);
}
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
g_inForEachExpression = FALSE;
//g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b().
g_code->codify(yytext);
@@ -3184,7 +3183,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
g_theVarContext.pushScope();
}
g_theVarContext.addVariable(g_parmType,g_parmName);
- //g_theCallContext.popScope();
+ //g_theCallContext.popScope(g_name, g_type);
g_parmType.resize(0);g_parmName.resize(0);
int index = g_name.findRev("::");
DBG_CTX((stderr,"g_name=%s\n",g_name.data()));
@@ -3192,7 +3191,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
{
QCString scope = g_name.left(index);
if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::");
- ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
+ const ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope);
if (cd)
{
setClassScope(cd->name());
@@ -3553,6 +3552,24 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
BEGIN(SkipComment);
}
}
+<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line
+ if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS))
+ {
+ g_lastSpecialCContext = YY_START;
+ BEGIN(RemoveSpecialCComment);
+ }
+ else
+ {
+ // check is to prevent getting stuck in skipping C++ comments
+ if (YY_START != SkipCxxComment)
+ {
+ g_lastCContext = YY_START ;
+ }
+ startFontClass("comment");
+ g_code->codify(yytext);
+ BEGIN(SkipComment);
+ }
+ }
<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line
if (Config_getBool(STRIP_CODE_COMMENTS))
{
@@ -3626,11 +3643,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\"
}
<*>"("|"[" {
g_code->codify(yytext);
- g_theCallContext.pushScope();
+ g_theCallContext.pushScope(g_name, g_type);
}
<*>")"|"]" {
g_code->codify(yytext);
- g_theCallContext.popScope();
+ g_theCallContext.popScope(g_name, g_type);
}
<*>\n {
g_yyColNr++;
@@ -3719,7 +3736,7 @@ void resetCCodeParserState()
void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s,
SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs)
{
//printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n",
diff --git a/src/commentcnv.l b/src/commentcnv.l
index 6b08d74..031b6f5 100644
--- a/src/commentcnv.l
+++ b/src/commentcnv.l
@@ -266,7 +266,7 @@ void replaceComment(int offset);
else
{
g_pythonDocString = TRUE;
- g_nestingCount=0;
+ g_nestingCount=1;
g_commentStack.clear(); /* to be on the save side */
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
@@ -281,7 +281,7 @@ void replaceComment(int offset);
else
{
copyToOutput(yytext,(int)yyleng);
- g_nestingCount=0;
+ g_nestingCount=0; // Fortran doesn't have an end comment
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
@@ -298,7 +298,7 @@ void replaceComment(int offset);
if (isFixedForm && (g_col == 0))
{
copyToOutput(yytext,(int)yyleng);
- g_nestingCount=0;
+ g_nestingCount=0; // Fortran doesn't have an end comment
g_commentStack.clear(); /* to be on the safe side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
@@ -399,8 +399,12 @@ void replaceComment(int offset);
copyToOutput(yytext,(int)yyleng);
}
<Scan>"/*"[*!]? { /* start of a C comment */
+ if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
+ {
+ REJECT;
+ }
g_specialComment=(int)yyleng==3;
- g_nestingCount=0;
+ g_nestingCount=1;
g_commentStack.clear(); /* to be on the save side */
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
@@ -414,7 +418,7 @@ void replaceComment(int offset);
else
{
copyToOutput(yytext,(int)yyleng);
- g_nestingCount=0;
+ g_nestingCount=0; // Python doesn't have an end comment for #
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
@@ -429,7 +433,7 @@ void replaceComment(int offset);
{
g_vhdl = TRUE;
copyToOutput(yytext,(int)yyleng);
- g_nestingCount=0;
+ g_nestingCount=0; // VHDL doesn't have an end comment
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
@@ -443,7 +447,7 @@ void replaceComment(int offset);
else
{
copyToOutput(yytext,(int)yyleng);
- g_nestingCount=0;
+ g_nestingCount=0; // Fortran doesn't have an end comment
g_commentStack.clear(); /* to be on the save side */
BEGIN(CComment);
g_commentStack.push(new CommentCtx(g_lineNr));
@@ -660,25 +664,30 @@ void replaceComment(int offset);
}
}
<CComment>"/"+"*" { /* nested C comment */
+ if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
+ {
+ REJECT;
+ }
g_nestingCount++;
g_commentStack.push(new CommentCtx(g_lineNr));
copyToOutput(yytext,(int)yyleng);
}
<CComment>"*"+"/" { /* end of C comment */
- if (g_lang==SrcLangExt_Python)
+ if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl))
{
REJECT;
}
else
{
copyToOutput(yytext,(int)yyleng);
+ g_nestingCount--;
if (g_nestingCount<=0)
{
BEGIN(Scan);
}
else
{
- g_nestingCount--;
+ //g_nestingCount--;
delete g_commentStack.pop();
}
}
@@ -1111,7 +1120,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
}
tmp += ")";
warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. "
- "Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment
+ "Nesting level %d %s",g_nestingCount,tmp.data());
}
g_commentStack.clear();
g_nestingCount = 0;
diff --git a/src/commentscan.h b/src/commentscan.h
index 75cd99f..7d2189f 100644
--- a/src/commentscan.h
+++ b/src/commentscan.h
@@ -85,13 +85,5 @@ bool parseCommentBlock(ParserInterface *parser,
bool &newEntryNeeded
);
-void groupEnterFile(const char *file,int line);
-void groupLeaveFile(const char *file,int line);
-void groupLeaveCompound(const char *file,int line,const char *name);
-void groupEnterCompound(const char *file,int line,const char *name);
-void openGroup(Entry *e,const char *file,int line);
-void closeGroup(Entry *,const char *file,int line,bool foundInline=FALSE);
-void initGroupInfo(Entry *e);
-
#endif
diff --git a/src/commentscan.l b/src/commentscan.l
index 0ca293c..a52821c 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -147,30 +147,30 @@ static DocCmdMap docCmdMap[] =
// command name handler function ends brief description
{ "brief", &handleBrief, FALSE },
{ "short", &handleBrief, FALSE },
- { "fn", &handleFn, FALSE },
- { "var", &handleFn, FALSE },
- { "typedef", &handleFn, FALSE },
- { "property", &handleFn, FALSE },
- { "def", &handleDef, FALSE },
+ { "fn", &handleFn, TRUE },
+ { "var", &handleFn, TRUE },
+ { "typedef", &handleFn, TRUE },
+ { "property", &handleFn, TRUE },
+ { "def", &handleDef, TRUE },
{ "overload", &handleOverload, FALSE },
- { "enum", &handleEnum, FALSE },
- { "defgroup", &handleDefGroup, FALSE },
- { "addtogroup", &handleAddToGroup, FALSE },
- { "weakgroup", &handleWeakGroup, FALSE },
- { "namespace", &handleNamespace, FALSE },
- { "package", &handlePackage, FALSE },
- { "class", &handleClass, FALSE },
+ { "enum", &handleEnum, TRUE },
+ { "defgroup", &handleDefGroup, TRUE },
+ { "addtogroup", &handleAddToGroup, TRUE },
+ { "weakgroup", &handleWeakGroup, TRUE },
+ { "namespace", &handleNamespace, TRUE },
+ { "package", &handlePackage, TRUE },
+ { "class", &handleClass, TRUE },
{ "headerfile", &handleHeaderFile, FALSE },
- { "protocol", &handleProtocol, FALSE },
- { "category", &handleCategory, FALSE },
- { "union", &handleUnion, FALSE },
- { "struct", &handleStruct, FALSE },
- { "interface", &handleInterface, FALSE },
- { "idlexcept", &handleIdlException, FALSE },
- { "page", &handlePage, FALSE },
- { "mainpage", &handleMainpage, FALSE },
- { "file", &handleFile, FALSE },
- { "dir", &handleDir, FALSE },
+ { "protocol", &handleProtocol, TRUE },
+ { "category", &handleCategory, TRUE },
+ { "union", &handleUnion, TRUE },
+ { "struct", &handleStruct, TRUE },
+ { "interface", &handleInterface, TRUE },
+ { "idlexcept", &handleIdlException, TRUE },
+ { "page", &handlePage, TRUE },
+ { "mainpage", &handleMainpage, TRUE },
+ { "file", &handleFile, TRUE },
+ { "dir", &handleDir, TRUE },
{ "example", &handleExample, FALSE },
{ "details", &handleDetails, TRUE },
{ "name", &handleName, FALSE },
@@ -210,7 +210,7 @@ static DocCmdMap docCmdMap[] =
{ "elseif", &handleElseIf, FALSE },
{ "else", &handleElse, FALSE },
{ "endif", &handleEndIf, FALSE },
- { "ingroup", &handleIngroup, FALSE },
+ { "ingroup", &handleIngroup, TRUE },
{ "nosubgrouping", &handleNoSubGrouping, FALSE },
{ "showinitializer", &handleShowInitializer, FALSE },
{ "hideinitializer", &handleHideInitializer, FALSE },
@@ -386,11 +386,6 @@ class GuardedSection
bool m_parentVisible;
};
-void openGroup(Entry *e,const char *file,int line);
-void closeGroup(Entry *e,const char *file,int line,bool foundInline=FALSE);
-void initGroupInfo(Entry *e);
-static void groupAddDocs(Entry *e);
-
/* -----------------------------------------------------------------
*
* statics
@@ -451,20 +446,11 @@ static bool g_insideParBlock;
//-----------------------------------------------------------------------------
-static QStack<Grouping> g_autoGroupStack;
-static int g_memberGroupId = DOX_NOGROUP;
-static QCString g_memberGroupHeader;
-static QCString g_memberGroupDocs;
-static QCString g_memberGroupRelates;
-static QCString g_compoundName;
-
-//-----------------------------------------------------------------------------
-
static void initParser()
{
g_sectionLabel.resize(0);
g_sectionTitle.resize(0);
- g_memberGroupHeader.resize(0);
+ Doxygen::docGroup.clearHeader();
g_insideParBlock = FALSE;
}
@@ -1218,12 +1204,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
}
<Comment>{B}*{CMD}"{" { // begin of a group
//langParser->handleGroupStartCommand(g_memberGroupHeader);
- openGroup(current,yyFileName,yyLineNr);
+ Doxygen::docGroup.open(current,yyFileName,yyLineNr);
}
<Comment>{B}*{CMD}"}" { // end of a group
//langParser->handleGroupEndCommand();
- closeGroup(current,yyFileName,yyLineNr,TRUE);
- g_memberGroupHeader.resize(0);
+ Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE);
+ Doxygen::docGroup.clearHeader();
parseMore=TRUE;
needNewEntry = TRUE;
#if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33))
@@ -1576,7 +1562,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
yyLineNr++;
addOutput('\n');
}
-<GroupDocArg2>[^\n\*]+ { // title (stored in type)
+<GroupDocArg2>[^\n\\]+ { // title (stored in type)
current->type += yytext;
current->type = current->type.stripWhiteSpace();
}
@@ -1594,11 +1580,16 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput('\n');
BEGIN( Comment );
}
+<GroupDocArg2>. { // title (stored in type)
+ current->type += yytext;
+ current->type = current->type.stripWhiteSpace();
+ }
/* --------- handle arguments of page/mainpage command ------------------- */
<PageDocArg1>{FILE} { // first argument; page name
current->name = stripQuotes(yytext);
+ current->args = "";
BEGIN( PageDocArg2 );
}
<PageDocArg1>{LC} { yyLineNr++;
@@ -1615,17 +1606,21 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
}
<PageDocArg1>. { // ignore other stuff
}
-<PageDocArg2>.*"\n" { // second argument; page title
- yyLineNr++;
+<PageDocArg2>{DOCNL} { // second argument; page title
+ if (*yytext=='\n') yyLineNr++;
+ addOutput('\n');
+ BEGIN( Comment );
+ }
+<PageDocArg2>{CMD}[<>] {
// bug 748927
QCString tmp = yytext;
tmp = substitute(substitute(tmp,"@<","&lt;"),"@>","&gt;");
tmp = substitute(substitute(tmp,"\\<","&lt;"),"\\>","&gt;");
- current->args = tmp;
- addOutput('\n');
- BEGIN( Comment );
+ current->args += tmp;
}
-
+<PageDocArg2>. {
+ current->args += yytext;
+ }
/* --------- handle arguments of the param command ------------ */
<ParamArg1>{ID}/{B}*"," {
addOutput(yytext);
@@ -1895,17 +1890,20 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput('\n');
}
<FormatBlock>"/*" { // start of a C-comment
- g_commentCount++;
+ if (!(blockName=="code" || blockName=="verbatim")) g_commentCount++;
addOutput(yytext);
}
<FormatBlock>"*/" { // end of a C-comment
addOutput(yytext);
- g_commentCount--;
- if (g_commentCount<0 && blockName!="verbatim")
- {
- warn(yyFileName,yyLineNr,
+ if (!(blockName=="code" || blockName=="verbatim"))
+ {
+ g_commentCount--;
+ if (g_commentCount<0)
+ {
+ warn(yyFileName,yyLineNr,
"found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data());
- }
+ }
+ }
}
<FormatBlock>. {
addOutput(*yytext);
@@ -1965,6 +1963,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
addOutput(*yytext);
}
<GuardParamEnd>{B}*{DOCNL} {
+ lineCount();
g_spaceBeforeIf.resize(0);
BEGIN(Comment);
}
@@ -2119,10 +2118,10 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
<NameParam>{LC} { // line continuation
yyLineNr++;
addOutput('\n');
- g_memberGroupHeader+=' ';
+ Doxygen::docGroup.appendHeader(' ');
}
<NameParam>. { // ignore other stuff
- g_memberGroupHeader+=*yytext;
+ Doxygen::docGroup.appendHeader(*yytext);
current->name+=*yytext;
}
@@ -2298,7 +2297,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
if (*yytext=='\n') yyLineNr++;
addOutput('\n');
setOutput(OutputDoc);
- addOutput("\\copydetails ");
+ addOutput(" \\copydetails ");
addOutput(g_copyDocArg);
addOutput("\n");
BEGIN(Comment);
@@ -2359,6 +2358,7 @@ static bool handleDefGroup(const QCString &, const QCStringList &)
{
bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC);
current->groupDocType = Entry::GROUPDOC_NORMAL;
+ setOutput(OutputBrief);
BEGIN( GroupDocArg1 );
return stop;
}
@@ -2462,6 +2462,7 @@ static bool handleMainpage(const QCString &, const QCStringList &)
{
current->name = "mainpage";
}
+ current->name = "";
BEGIN( PageDocArg2 );
return stop;
}
@@ -2540,11 +2541,11 @@ static bool handleName(const QCString &, const QCStringList &)
bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC);
if (!stop)
{
- g_memberGroupHeader.resize(0);
+ Doxygen::docGroup.clearHeader();
BEGIN( NameParam );
- if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group
+ if (!Doxygen::docGroup.isEmpty()) // end of previous member group
{
- closeGroup(current,yyFileName,yyLineNr,TRUE);
+ Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE);
}
}
return stop;
@@ -3192,9 +3193,9 @@ bool parseCommentBlock(/* in */ ParserInterface *parser,
}
if (current->section==Entry::MEMBERGRP_SEC &&
- g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet
+ Doxygen::docGroup.isEmpty()) // @name section but no group started yet
{
- openGroup(current,yyFileName,yyLineNr);
+ Doxygen::docGroup.open(current,yyFileName,yyLineNr,true);
}
Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n"
@@ -3208,7 +3209,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser,
checkFormula();
prot = protection;
- groupAddDocs(curEntry);
+ Doxygen::docGroup.addDocs(curEntry);
newEntryNeeded = needNewEntry;
@@ -3227,185 +3228,6 @@ bool parseCommentBlock(/* in */ ParserInterface *parser,
return parseMore;
}
-//---------------------------------------------------------------------------
-
-void groupEnterFile(const char *fileName,int)
-{
- g_autoGroupStack.setAutoDelete(TRUE);
- g_autoGroupStack.clear();
- g_memberGroupId = DOX_NOGROUP;
- g_memberGroupDocs.resize(0);
- g_memberGroupRelates.resize(0);
- g_compoundName=fileName;
-}
-
-void groupLeaveFile(const char *fileName,int line)
-{
- //if (g_memberGroupId!=DOX_NOGROUP)
- //{
- // warn(fileName,line,"end of file while inside a member group\n");
- //}
- g_memberGroupId=DOX_NOGROUP;
- g_memberGroupRelates.resize(0);
- g_memberGroupDocs.resize(0);
- if (!g_autoGroupStack.isEmpty())
- {
- warn(fileName,line,"end of file while inside a group\n");
- }
-}
-
-void groupEnterCompound(const char *fileName,int line,const char *name)
-{
- if (g_memberGroupId!=DOX_NOGROUP)
- {
- warn(fileName,line,"try to put compound %s inside a member group\n",name);
- }
- g_memberGroupId=DOX_NOGROUP;
- g_memberGroupRelates.resize(0);
- g_memberGroupDocs.resize(0);
- g_compoundName = name;
- int i = g_compoundName.find('(');
- if (i!=-1)
- {
- g_compoundName=g_compoundName.left(i); // strip category (Obj-C)
- }
- if (g_compoundName.isEmpty())
- {
- g_compoundName=fileName;
- }
- //printf("groupEnterCompound(%s)\n",name);
-}
-
-void groupLeaveCompound(const char *,int,const char * /*name*/)
-{
- //printf("groupLeaveCompound(%s)\n",name);
- //if (g_memberGroupId!=DOX_NOGROUP)
- //{
- // warn(fileName,line,"end of compound %s while inside a member group\n",name);
- //}
- g_memberGroupId=DOX_NOGROUP;
- g_memberGroupRelates.resize(0);
- g_memberGroupDocs.resize(0);
- g_compoundName.resize(0);
-}
-
-static int findExistingGroup(int &groupId,const MemberGroupInfo *info)
-{
- //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data());
- QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict);
- MemberGroupInfo *mi;
- for (di.toFirst();(mi=di.current());++di)
- {
- if (g_compoundName==mi->compoundName && // same file or scope
- !mi->header.isEmpty() && // not a nameless group
- qstricmp(mi->header,info->header)==0 // same header name
- )
- {
- //printf("Found it!\n");
- return (int)di.currentKey(); // put the item in this group
- }
- }
- groupId++; // start new group
- return groupId;
-}
-
-void openGroup(Entry *e,const char *,int)
-{
- //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n",
- // e->name.data(),e->section,g_autoGroupStack.count());
- if (e->section==Entry::GROUPDOC_SEC) // auto group
- {
- g_autoGroupStack.push(new Grouping(e->name,e->groupingPri()));
- }
- else // start of a member group
- {
- //printf(" membergroup id=%d %s\n",g_memberGroupId,g_memberGroupHeader.data());
- if (g_memberGroupId==DOX_NOGROUP) // no group started yet
- {
- static int curGroupId=0;
-
- MemberGroupInfo *info = new MemberGroupInfo;
- info->header = g_memberGroupHeader.stripWhiteSpace();
- info->compoundName = g_compoundName;
- g_memberGroupId = findExistingGroup(curGroupId,info);
- //printf(" use membergroup %d\n",g_memberGroupId);
- Doxygen::memGrpInfoDict.insert(g_memberGroupId,info);
-
- g_memberGroupRelates = e->relates;
- e->mGrpId = g_memberGroupId;
- }
- }
-}
-
-void closeGroup(Entry *e,const char *fileName,int line,bool foundInline)
-{
- //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) g_autoGroupStack=%d\n",
- // e->name.data(),e->section,fileName,line,g_autoGroupStack.count());
- if (g_memberGroupId!=DOX_NOGROUP) // end of member group
- {
- MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
- if (info) // known group
- {
- info->doc = g_memberGroupDocs;
- info->docFile = fileName;
- info->docLine = line;
- }
- g_memberGroupId=DOX_NOGROUP;
- g_memberGroupRelates.resize(0);
- g_memberGroupDocs.resize(0);
- if (!foundInline) e->mGrpId=DOX_NOGROUP;
- //printf("new group id=%d\n",g_memberGroupId);
- }
- else if (!g_autoGroupStack.isEmpty()) // end of auto group
- {
- Grouping *grp = g_autoGroupStack.pop();
- // see bug577005: we should not remove the last group for e
- if (!foundInline) e->groups->removeLast();
- //printf("Removing %s e=%p\n",grp->groupname.data(),e);
- delete grp;
- if (!foundInline) initGroupInfo(e);
- }
-}
-
-void initGroupInfo(Entry *e)
-{
- //printf("==> initGroup(id=%d,related=%s,e=%p)\n",g_memberGroupId,
- // g_memberGroupRelates.data(),e);
- e->mGrpId = g_memberGroupId;
- e->relates = g_memberGroupRelates;
- if (!g_autoGroupStack.isEmpty())
- {
- //printf("Appending group %s to %s: count=%d entry=%p\n",
- // g_autoGroupStack.top()->groupname.data(),
- // e->name.data(),e->groups->count(),e);
- e->groups->append(new Grouping(*g_autoGroupStack.top()));
- }
-}
-
-static void groupAddDocs(Entry *e)
-{
- if (e->section==Entry::MEMBERGRP_SEC)
- {
- g_memberGroupDocs=e->brief.stripWhiteSpace();
- e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine);
- if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty())
- {
- g_memberGroupDocs+="\n\n";
- }
- g_memberGroupDocs+=e->doc;
- MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId);
- if (info)
- {
- info->doc = g_memberGroupDocs;
- info->docFile = e->docFile;
- info->docLine = e->docLine;
- info->setRefItems(e->sli);
- }
- e->doc.resize(0);
- e->brief.resize(0);
- }
-}
-
static void handleGuard(const QCString &expr)
{
CondParser prs;
diff --git a/src/config.xml b/src/config.xml
index 8820fe7..8e19d67 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -105,7 +105,6 @@ PROJECT_NAME = Example
INPUT = example.cc example.h
WARNINGS = YES
TAGFILES = qt.tag
-PERL_PATH = /usr/local/bin/perl
SEARCHENGINE = NO
\endverbatim
@@ -120,7 +119,6 @@ INPUT = examples/examples.doc src
FILE_PATTERNS = *.cc *.h
INCLUDE_PATH = examples
TAGFILES = qt.tag
-PERL_PATH = /usr/bin/perl
SEARCHENGINE = YES
\endverbatim
@@ -480,6 +478,17 @@ Go to the <a href="commands.html">next</a> section or return to the
]]>
</docs>
</option>
+ <option type='bool' id='JAVADOC_BANNER' defval='0'>
+ <docs>
+<![CDATA[
+ If the \c JAVADOC_BANNER tag is set to \c YES then doxygen
+ will interpret a line such as "/***************" as being the
+ beginning of a Javadoc-style comment "banner". If set to \c NO, the
+ Javadoc-style will behave just like regular comments and it will
+ not be interpreted by doxygen.
+]]>
+ </docs>
+ </option>
<option type='bool' id='QT_AUTOBRIEF' defval='0'>
<docs>
<![CDATA[
@@ -951,8 +960,8 @@ Go to the <a href="commands.html">next</a> section or return to the
will only generate file names in lower-case letters. If set to
\c YES, upper-case letters are also allowed. This is useful if you have
classes or files whose names only differ in case and if your file system
- supports case sensitive file names. Windows and Mac users are advised to set this
- option to \c NO.
+ supports case sensitive file names. Windows (including Cygwin) ands
+ Mac users are advised to set this option to \c NO.
]]>
</docs>
</option>
@@ -3229,14 +3238,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
]]>
</docs>
</option>
- <option type='string' id='PERL_PATH' format='file' defval='/usr/bin/perl' abspath='1'>
- <docs>
-<![CDATA[
- The \c PERL_PATH should be the absolute path and name of the perl script
- interpreter (i.e. the result of `'which perl'`).
-]]>
- </docs>
- </option>
</group>
<group name='Dot' docs='Configuration options related to the dot tool'>
<option type='bool' id='CLASS_DIAGRAMS' defval='1'>
@@ -3250,17 +3251,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs.
]]>
</docs>
</option>
- <option type='string' id='MSCGEN_PATH' format='dir' defval=''>
- <docs>
-<![CDATA[
- You can define message sequence charts within doxygen comments using the \ref cmdmsc "\\msc"
- command. Doxygen will then run the <a href="http://www.mcternan.me.uk/mscgen/">mscgen tool</a>) to
- produce the chart and insert it in the documentation. The <code>MSCGEN_PATH</code> tag allows you to
- specify the directory where the \c mscgen tool resides. If left empty the tool is assumed to
- be found in the default search path.
-]]>
- </docs>
- </option>
<option type='string' id='DIA_PATH' format='dir' defval=''>
<docs>
<![CDATA[
@@ -3639,5 +3629,7 @@ remove the intermediate dot files that are used to generate the various graphs.
<option type='obsolete' id='SYMBOL_CACHE_SIZE'/>
<option type='obsolete' id='XML_SCHEMA'/>
<option type='obsolete' id='XML_DTD'/>
+ <option type='obsolete' id='PERL_PATH'/>
+ <option type='obsolete' id='MSCGEN_PATH'/>
</group>
</doxygenconfig>
diff --git a/src/configimpl.l b/src/configimpl.l
index f07509a..72c826d 100644
--- a/src/configimpl.l
+++ b/src/configimpl.l
@@ -699,12 +699,12 @@ static void readIncludeFile(const char *incName)
%%
<*>\0x0d
-<PreStart>"##".*"\n" { config->appendStartComment(yytext);}
+<PreStart>"##".*"\n" { config->appendStartComment(yytext);yyLineNr++;}
<PreStart>. {
BEGIN(Start);
unput(*yytext);
}
-<Start,GetString,GetStrList,GetBool,SkipInvalid>"##".*"\n" { config->appendUserComment(yytext);}
+<Start,GetString,GetStrList,GetBool,SkipInvalid>"##".*"\n" { config->appendUserComment(yytext);yyLineNr++;}
<Start,GetString,GetStrList,GetBool,SkipInvalid>"#" { BEGIN(SkipComment); }
<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { QCString cmd=yytext;
cmd=cmd.left(cmd.length()-1).stripWhiteSpace();
@@ -1570,30 +1570,6 @@ void Config::checkAndCorrect()
dotPath="";
}
- // check mscgen path
- QCString &mscgenPath = ConfigImpl_getString("MSCGEN_PATH");
- if (!mscgenPath.isEmpty())
- {
- QFileInfo dp(mscgenPath+"/mscgen"+portable_commandExtension());
- if (!dp.exists() || !dp.isFile())
- {
- warn_uncond("the mscgen tool could not be found at %s\n",mscgenPath.data());
- mscgenPath="";
- }
- else
- {
- mscgenPath=dp.dirPath(TRUE).utf8()+"/";
-#if defined(_WIN32) // convert slashes
- uint i=0,l=mscgenPath.length();
- for (i=0;i<l;i++) if (mscgenPath.at(i)=='/') mscgenPath.at(i)='\\';
-#endif
- }
- }
- else // make sure the string is empty but not null!
- {
- mscgenPath="";
- }
-
// check plantuml path
QCString &plantumlJarPath = ConfigImpl_getString("PLANTUML_JAR_PATH");
if (!plantumlJarPath.isEmpty())
diff --git a/src/constexp.h b/src/constexp.h
index d84e94e..8bf582e 100644
--- a/src/constexp.h
+++ b/src/constexp.h
@@ -22,12 +22,21 @@
#include "cppvalue.h"
#include <qcstring.h>
-extern bool parseconstexp(const char *fileName,int line,const QCString &s);
-extern int constexpYYparse();
-extern int constexpYYdebug;
-extern QCString g_strToken;
-extern CPPValue g_resultValue;
-extern QCString g_constExpFileName;
-extern int g_constExpLineNr;
+#define YYSTYPE CPPValue
+typedef void* yyscan_t;
+struct constexpYY_state
+{
+ QCString g_strToken;
+ CPPValue g_resultValue;
+ int g_constExpLineNr;
+ QCString g_constExpFileName;
+
+ const char *g_inputString;
+ int g_inputPosition;
+};
+extern bool parseconstexp(const char *fileName,int line,const QCString &s);
+extern int constexpYYparse(yyscan_t);
+extern int constexpYYlex(YYSTYPE *lvalp, yyscan_t);
+struct constexpYY_state* constexpYYget_extra (yyscan_t yyscanner );
#endif
diff --git a/src/constexp.l b/src/constexp.l
index 8a7db04..bd42104 100644
--- a/src/constexp.l
+++ b/src/constexp.l
@@ -17,44 +17,30 @@
*/
%option never-interactive
%option prefix="constexpYY"
+%option nounput
+%option reentrant bison-bridge
+%option extra-type="struct constexpYY_state *"
%{
#include "constexp.h"
#include "cppvalue.h"
-#include "ce_parse.h" // generated header file
+#include "ce_parse.hpp" // generated header file
#include "message.h"
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 1
-
-QCString g_strToken;
-CPPValue g_resultValue;
-int g_constExpLineNr;
-QCString g_constExpFileName;
-static const char *g_inputString;
-static int g_inputPosition;
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+static int yyread(char *buf,int max_size,yyscan_t yyscanner);
-static int yyread(char *buf,int max_size)
-{
- int c=0;
- while( c < max_size && g_inputString[g_inputPosition] )
- {
- *buf = g_inputString[g_inputPosition++] ;
- c++; buf++;
- }
- return c;
-}
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
%}
CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?)
-%option nounput
%%
@@ -83,44 +69,73 @@ CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?)
"(" { return TOK_LPAREN; }
")" { return TOK_RPAREN; }
"'"(([^\'\n\r\\]+)|(\\(([ntvbrfa\\?'\"])|([0-9]+)|([xX][0-9a-fA-F]+))))"'" {
- g_strToken=yytext;
+ yyextra->g_strToken=yytext;
return TOK_CHARACTER;
}
-0[0-7]*{CONSTSUFFIX}? { g_strToken=yytext;
+0[0-7]*{CONSTSUFFIX}? { yyextra->g_strToken=yytext;
return TOK_OCTALINT;
}
-[1-9][0-9]*{CONSTSUFFIX}? { g_strToken=yytext;
+[1-9][0-9]*{CONSTSUFFIX}? { yyextra->g_strToken=yytext;
return TOK_DECIMALINT;
}
-(0x|0X)[0-9a-fA-F]+{CONSTSUFFIX}? { g_strToken=yytext+2;
+(0x|0X)[0-9a-fA-F]+{CONSTSUFFIX}? { yyextra->g_strToken=yytext+2;
return TOK_HEXADECIMALINT;
}
(([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE]([\-\+])?[0-9]+)?([fFlL])? {
- g_strToken=yytext; return TOK_FLOAT;
+ yyextra->g_strToken=yytext; return TOK_FLOAT;
}
([0-9]+[eE])([\-\+])?[0-9]+([fFlL])? {
- g_strToken=yytext; return TOK_FLOAT;
+ yyextra->g_strToken=yytext; return TOK_FLOAT;
}
.
\n
%%
+static int yyread(char *buf,int max_size,yyscan_t yyscanner)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ int c=0;
+ while( c < max_size && yyextra->g_inputString[yyextra->g_inputPosition] )
+ {
+ *buf = yyextra->g_inputString[yyextra->g_inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+
+static yyscan_t yyscanner;
+static struct constexpYY_state constexpYY_extra;
+
bool parseconstexp(const char *fileName,int lineNr,const QCString &s)
{
+ constexpYYlex_init_extra(&constexpYY_extra, &yyscanner);
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+
+#ifdef FLEX_DEBUG
+ yyset_debug(1,yyscanner);
+#endif
+
+ yyextra->g_constExpFileName = fileName;
+ yyextra->g_constExpLineNr = lineNr;
+ yyextra->g_inputString = s;
+ yyextra->g_inputPosition = 0;
+ constexpYYrestart( yyin, yyscanner );
+
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
//printf("Expression: `%s'\n",s.data());
- g_constExpFileName = fileName;
- g_constExpLineNr = lineNr;
- g_inputString = s;
- g_inputPosition = 0;
- constexpYYrestart( constexpYYin );
- constexpYYparse();
+
+ constexpYYparse(yyscanner);
+
//printf("Result: %ld\n",(long)g_resultValue);
printlex(yy_flex_debug, FALSE, __FILE__, fileName);
- return (long)g_resultValue!=0;
+ bool result = (long)yyextra->g_resultValue!=0;
+
+ constexpYYlex_destroy(yyscanner);
+ return result;
}
extern "C" {
- int constexpYYwrap() { return 1; }
+ int constexpYYwrap(yyscan_t yyscanner) { return 1; }
}
diff --git a/src/constexp.y b/src/constexp.y
index f87ebf3..62a51f3 100644
--- a/src/constexp.y
+++ b/src/constexp.y
@@ -26,24 +26,24 @@
#define MSDOS
#endif
-#define YYSTYPE CPPValue
#include <stdio.h>
#include <stdlib.h>
-int constexpYYerror(const char *s)
+int constexpYYerror(yyscan_t yyscanner, const char *s)
{
- warn(g_constExpFileName,g_constExpLineNr,
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ warn(yyextra->g_constExpFileName, yyextra->g_constExpLineNr,
"preprocessing issue while doing constant expression evaluation: %s",s);
return 0;
}
-int constexpYYlex();
-
%}
-%no-lines
-%name-prefix="constexpYY"
+%name-prefix "constexpYY"
+%define api.pure full
+%lex-param {yyscan_t yyscanner}
+%parse-param {yyscan_t yyscanner}
%token TOK_QUESTIONMARK
%token TOK_COLON
@@ -78,7 +78,10 @@ int constexpYYlex();
%%
start: constant_expression
- { g_resultValue = $1; return 0; }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ yyextra->g_resultValue = $1; return 0;
+ }
;
constant_expression: logical_or_expression
@@ -267,15 +270,30 @@ primary_expression: constant
;
constant: TOK_OCTALINT
- { $$ = parseOctal(); }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ $$ = parseOctal(yyextra->g_strToken);
+ }
| TOK_DECIMALINT
- { $$ = parseDecimal(); }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ $$ = parseDecimal(yyextra->g_strToken);
+ }
| TOK_HEXADECIMALINT
- { $$ = parseHexadecimal(); }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ $$ = parseHexadecimal(yyextra->g_strToken);
+ }
| TOK_CHARACTER
- { $$ = parseCharacter(); }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ $$ = parseCharacter(yyextra->g_strToken);
+ }
| TOK_FLOAT
- { $$ = parseFloat(); }
+ {
+ struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner);
+ $$ = parseFloat(yyextra->g_strToken);
+ }
;
%%
diff --git a/src/context.cpp b/src/context.cpp
index e14907f..49c9afa 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -39,6 +39,12 @@
#include "latexgen.h"
#include "latexdocvisitor.h"
#include "dot.h"
+#include "dotcallgraph.h"
+#include "dotclassgraph.h"
+#include "dotdirdeps.h"
+#include "dotgfxhierarchytable.h"
+#include "dotgroupcollaboration.h"
+#include "dotincldepgraph.h"
#include "diagram.h"
#include "example.h"
#include "membername.h"
@@ -1254,7 +1260,7 @@ TemplateVariant TranslateContext::get(const char *n) const
return p->get(n);
}
-static TemplateVariant parseDoc(Definition *def,const QCString &file,int line,
+static TemplateVariant parseDoc(const Definition *def,const QCString &file,int line,
const QCString &relPath,const QCString &docStr,bool isBrief)
{
TemplateVariant result;
@@ -1324,7 +1330,7 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q
return TemplateVariant(s.data(),TRUE);
}
-static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
+static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath)
{
static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
ParserInterface *pIntf = Doxygen::parserManager->getParser(fd->getDefFileExtension());
@@ -1341,7 +1347,7 @@ static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
fd->getLanguage(), // lang
FALSE, // isExampleBlock
0, // exampleName
- fd, // fileDef
+ const_cast<FileDef*>(fd), // fileDef, TODO: should be const
-1, // startLine
-1, // endLine
FALSE, // inlineFragment
@@ -1360,7 +1366,7 @@ static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
fd->getLanguage(), // lang
FALSE, // isExampleBlock
0, // exampleName
- fd, // fileDef
+ const_cast<FileDef*>(fd), // fileDef, TODO: should be const
-1, // startLine
-1, // endLine
FALSE, // inlineFragment
@@ -1387,7 +1393,7 @@ template<typename T>
class DefinitionContext
{
public:
- DefinitionContext(Definition *d) : m_def(d)
+ DefinitionContext(const Definition *d) : m_def(d)
{
assert(d!=0);
}
@@ -1574,9 +1580,9 @@ class DefinitionContext
return FALSE;
}
}
- void fillPath(Definition *def,TemplateList *list) const
+ void fillPath(const Definition *def,TemplateList *list) const
{
- Definition *outerScope = def->getOuterScope();
+ const Definition *outerScope = def->getOuterScope();
Definition::DefType type = def->definitionType();
if (outerScope && outerScope!=Doxygen::globalScope)
{
@@ -1618,7 +1624,7 @@ class DefinitionContext
protected:
struct Cachable : public Definition::Cookie
{
- Cachable(Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified),
+ Cachable(const Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified),
briefOutputFormat(ContextOutputFormat_Unspecified),
inbodyDocsOutputFormat(ContextOutputFormat_Unspecified)
{
@@ -1675,7 +1681,7 @@ class DefinitionContext
assert(c!=0);
return *c;
}
- Definition *m_def;
+ const Definition *m_def;
};
//%% }
@@ -1810,7 +1816,7 @@ TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const
class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
public:
- Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
+ Private(const ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd),
m_classDef(cd)
{
static bool init=FALSE;
@@ -1926,7 +1932,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
Cachable &cache = getCache();
if (!cache.classGraph)
{
- cache.classGraph.reset(new DotClassGraph(m_classDef,DotNode::Inheritance));
+ cache.classGraph.reset(new DotClassGraph(m_classDef,Inheritance));
}
return cache.classGraph.get();
}
@@ -2048,7 +2054,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
Cachable &cache = getCache();
if (!cache.collaborationGraph)
{
- cache.collaborationGraph.reset(new DotClassGraph(m_classDef,DotNode::Collaboration));
+ cache.collaborationGraph.reset(new DotClassGraph(m_classDef,Collaboration));
}
return cache.collaborationGraph.get();
}
@@ -2322,7 +2328,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
if (m_classDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_classDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->visibleInParentsDeclList())
@@ -2344,7 +2350,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
if (m_classDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_classDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->name().find('@')==-1 &&
@@ -2365,16 +2371,16 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
return m_classDef->compoundTypeString();
}
- void addTemplateDecls(Definition *d,TemplateList *tl) const
+ void addTemplateDecls(const Definition *d,TemplateList *tl) const
{
if (d->definitionType()==Definition::TypeClass)
{
- Definition *parent = d->getOuterScope();
+ const Definition *parent = d->getOuterScope();
if (parent)
{
addTemplateDecls(parent,tl);
}
- ClassDef *cd=dynamic_cast<ClassDef *>(d);
+ const ClassDef *cd=dynamic_cast<const ClassDef *>(d);
if (cd->templateArguments())
{
ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString());
@@ -2438,7 +2444,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
}
return cache.examples.get();
}
- void addMembers(ClassDef *cd,MemberListType lt) const
+ void addMembers(const ClassDef *cd,MemberListType lt) const
{
MemberList *ml = cd->getMemberList(lt);
if (ml)
@@ -2595,10 +2601,10 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
}
private:
- ClassDef *m_classDef;
+ const ClassDef *m_classDef;
struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable
{
- Cachable(ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd),
+ Cachable(const ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd),
inheritanceNodes(-1) { }
SharedPtr<IncludeInfoContext> includeInfo;
SharedPtr<InheritanceListContext> inheritsList;
@@ -2672,7 +2678,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst;
-ClassContext::ClassContext(ClassDef *cd) : RefCountedContext("ClassContext")
+ClassContext::ClassContext(const ClassDef *cd) : RefCountedContext("ClassContext")
{
//printf("ClassContext::ClassContext(%s)\n",cd?cd->name().data():"<none>");
p = new Private(cd);
@@ -2695,7 +2701,7 @@ TemplateVariant ClassContext::get(const char *n) const
class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private>
{
public:
- Private(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd),
+ Private(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd),
m_namespaceDef(nd)
{
static bool init=FALSE;
@@ -2764,7 +2770,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
if (m_namespaceDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (sliceOpt && (cd->compoundType()==ClassDef::Struct ||
@@ -2792,7 +2798,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
if (m_namespaceDef->getNamespaceSDict())
{
NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict());
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && !nd->isConstantGroup())
@@ -2814,7 +2820,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
if (m_namespaceDef->getNamespaceSDict())
{
NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict());
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && nd->isConstantGroup())
@@ -2932,7 +2938,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
if (m_namespaceDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->name().find('@')==-1 &&
@@ -2949,10 +2955,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
return cache.inlineClasses.get();
}
private:
- NamespaceDef *m_namespaceDef;
+ const NamespaceDef *m_namespaceDef;
struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable
{
- Cachable(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {}
+ Cachable(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {}
SharedPtr<TemplateList> classes;
SharedPtr<TemplateList> interfaces;
SharedPtr<TemplateList> namespaces;
@@ -2984,7 +2990,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri
PropertyMapper<NamespaceContext::Private> NamespaceContext::Private::s_inst;
-NamespaceContext::NamespaceContext(NamespaceDef *nd) : RefCountedContext("NamespaceContext")
+NamespaceContext::NamespaceContext(const NamespaceDef *nd) : RefCountedContext("NamespaceContext")
{
p = new Private(nd);
}
@@ -3006,7 +3012,7 @@ TemplateVariant NamespaceContext::get(const char *n) const
class FileContext::Private : public DefinitionContext<FileContext::Private>
{
public:
- Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
+ Private(const FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd)
{
if (fd==0) abort();
static bool init=FALSE;
@@ -3229,7 +3235,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
if (m_fileDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->visibleInParentsDeclList())
@@ -3251,7 +3257,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
if (m_fileDef->getNamespaceSDict())
{
NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict());
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && !nd->isConstantGroup())
@@ -3396,7 +3402,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
if (m_fileDef->getClassSDict())
{
ClassSDict::Iterator sdi(*m_fileDef->getClassSDict());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->name().find('@')==-1 &&
@@ -3418,10 +3424,10 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
}
private:
- FileDef *m_fileDef;
+ const FileDef *m_fileDef;
struct Cachable : public DefinitionContext<FileContext::Private>::Cachable
{
- Cachable(FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {}
+ Cachable(const FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {}
SharedPtr<IncludeInfoListContext> includeInfoList;
ScopedPtr<DotInclDepGraph> includeGraph;
ScopedPtr<DotInclDepGraph> includedByGraph;
@@ -3458,7 +3464,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
PropertyMapper<FileContext::Private> FileContext::Private::s_inst;
-FileContext::FileContext(FileDef *fd) : RefCountedContext("FileContext")
+FileContext::FileContext(const FileDef *fd) : RefCountedContext("FileContext")
{
p = new Private(fd);
}
@@ -3480,7 +3486,7 @@ TemplateVariant FileContext::get(const char *n) const
class DirContext::Private : public DefinitionContext<DirContext::Private>
{
public:
- Private(DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd)
+ Private(const DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd)
{
static bool init=FALSE;
if (!init)
@@ -3529,7 +3535,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
cache.dirs.reset(TemplateList::alloc());
const DirList &subDirs = m_dirDef->subDirs();
QListIterator<DirDef> it(subDirs);
- DirDef *dd;
+ const DirDef *dd;
for (it.toFirst();(dd=it.current());++it)
{
DirContext *dc = new DirContext(dd);
@@ -3548,7 +3554,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
if (files)
{
QListIterator<FileDef> it(*files);
- FileDef *fd;
+ const FileDef *fd;
for (it.toFirst();(fd=it.current());++it)
{
FileContext *fc = FileContext::alloc(fd);
@@ -3637,10 +3643,10 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
}
private:
- DirDef *m_dirDef;
+ const DirDef *m_dirDef;
struct Cachable : public DefinitionContext<DirContext::Private>::Cachable
{
- Cachable(DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {}
+ Cachable(const DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {}
SharedPtr<TemplateList> dirs;
SharedPtr<TemplateList> files;
ScopedPtr<DotDirDeps> dirDepsGraph;
@@ -3657,7 +3663,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private>
PropertyMapper<DirContext::Private> DirContext::Private::s_inst;
-DirContext::DirContext(DirDef *fd) : RefCountedContext("DirContext")
+DirContext::DirContext(const DirDef *fd) : RefCountedContext("DirContext")
{
p = new Private(fd);
}
@@ -3679,7 +3685,7 @@ TemplateVariant DirContext::get(const char *n) const
class PageContext::Private : public DefinitionContext<PageContext::Private>
{
public:
- Private(PageDef *pd,bool isMainPage,bool isExample)
+ Private(const PageDef *pd,bool isMainPage,bool isExample)
: DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage),
m_isExample(isExample)
{
@@ -3768,10 +3774,10 @@ class PageContext::Private : public DefinitionContext<PageContext::Private>
}
}
private:
- PageDef *m_pageDef;
+ const PageDef *m_pageDef;
struct Cachable : public DefinitionContext<PageContext::Private>::Cachable
{
- Cachable(PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd),
+ Cachable(const PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd),
exampleOutputFormat(ContextOutputFormat_Unspecified) { }
ScopedPtr<TemplateVariant> example;
ContextOutputFormat exampleOutputFormat;
@@ -3790,7 +3796,7 @@ class PageContext::Private : public DefinitionContext<PageContext::Private>
PropertyMapper<PageContext::Private> PageContext::Private::s_inst;
-PageContext::PageContext(PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext")
+PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext")
{
p = new Private(pd,isMainPage,isExample);
}
@@ -3949,7 +3955,7 @@ class TextGeneratorFactory
virtual ~TextGeneratorFactory() {}
};
-TemplateVariant createLinkedText(Definition *def,const QCString &relPath,const QCString &text)
+TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,const QCString &text)
{
QGString s;
FTextStream ts(&s);
@@ -4023,7 +4029,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
s_inst.addProperty("isSealed", &Private::isSealed);
s_inst.addProperty("isImplementation", &Private::isImplementation);
s_inst.addProperty("isExternal", &Private::isExternal);
- s_inst.addProperty("isAlias", &Private::isAlias);
+ s_inst.addProperty("isTypeAlias", &Private::isTypeAlias);
s_inst.addProperty("isDefault", &Private::isDefault);
s_inst.addProperty("isDelete", &Private::isDelete);
s_inst.addProperty("isNoExcept", &Private::isNoExcept);
@@ -4334,9 +4340,9 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
{
return m_memberDef->isExternal();
}
- TemplateVariant isAlias() const
+ TemplateVariant isTypeAlias() const
{
- return m_memberDef->isAlias();
+ return m_memberDef->isTypeAlias();
}
TemplateVariant isDefault() const
{
@@ -4452,7 +4458,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
Cachable &cache = getCache();
if (!cache.anonymousType)
{
- ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
+ const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType();
if (cd)
{
cache.anonymousType.reset(ClassContext::alloc(cd));
@@ -4508,7 +4514,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
Cachable &cache = getCache();
if (!cache.enumValues)
{
- MemberList *ml = m_memberDef->enumFieldList();
+ const MemberList *ml = m_memberDef->enumFieldList();
if (ml)
{
cache.enumValues.reset(MemberListContext::alloc(ml));
@@ -4538,7 +4544,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
}
TemplateVariant templateAlias() const
{
- if (m_memberDef->isAlias())
+ if (m_memberDef->isTypeAlias())
{
return createLinkedText(m_memberDef,relPathAsString(),
QCString(" = ")+m_memberDef->typeString());
@@ -4638,7 +4644,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
return createLinkedText(m_memberDef,relPathAsString(),
m_memberDef->displayDefinition());
}
- ArgumentList *getDefArgList() const
+ const ArgumentList *getDefArgList() const
{
return (m_memberDef->isDocsForDefinition()) ?
m_memberDef->argumentList() : m_memberDef->declArgumentList();
@@ -4648,7 +4654,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
Cachable &cache = getCache();
if (!cache.arguments)
{
- ArgumentList *defArgList = getDefArgList();
+ const ArgumentList *defArgList = getDefArgList();
if (defArgList && !m_memberDef->isProperty())
{
cache.arguments.reset(ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString()));
@@ -4666,27 +4672,27 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
}
TemplateVariant hasConstQualifier() const
{
- ArgumentList *al = getDefArgList();
+ const ArgumentList *al = getDefArgList();
return al ? al->constSpecifier : FALSE;
}
TemplateVariant hasVolatileQualifier() const
{
- ArgumentList *al = getDefArgList();
+ const ArgumentList *al = getDefArgList();
return al ? al->volatileSpecifier : FALSE;
}
TemplateVariant hasRefQualifierLValue() const
{
- ArgumentList *al = getDefArgList();
+ const ArgumentList *al = getDefArgList();
return al ? al->refQualifier==RefQualifierLValue : FALSE;
}
TemplateVariant hasRefQualifierRValue() const
{
- ArgumentList *al = getDefArgList();
+ const ArgumentList *al = getDefArgList();
return al ? al->refQualifier==RefQualifierRValue : FALSE;
}
TemplateVariant trailingReturnType() const
{
- ArgumentList *al = getDefArgList();
+ const ArgumentList *al = getDefArgList();
if (al && !al->trailingReturnType.isEmpty())
{
return createLinkedText(m_memberDef,relPathAsString(),
@@ -4703,7 +4709,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
}
void addTemplateDecls(TemplateList *tl) const
{
- ClassDef *cd=m_memberDef->getClassDef();
+ const ClassDef *cd=m_memberDef->getClassDef();
if (m_memberDef->definitionTemplateParameterLists())
{
QListIterator<ArgumentList> ali(*m_memberDef->definitionTemplateParameterLists());
@@ -4813,7 +4819,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
cache.implements.reset(TemplateList::alloc());
if (md)
{
- ClassDef *cd = md->getClassDef();
+ const ClassDef *cd = md->getClassDef();
if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
{
MemberContext *mc = MemberContext::alloc(md);
@@ -4832,7 +4838,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
cache.reimplements.reset(TemplateList::alloc());
if (md)
{
- ClassDef *cd = md->getClassDef();
+ const ClassDef *cd = md->getClassDef();
if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
{
MemberContext *mc = MemberContext::alloc(md);
@@ -4855,7 +4861,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
MemberDef *md=0;
for (mli.toFirst();(md=mli.current());++mli)
{
- ClassDef *cd = md->getClassDef();
+ const ClassDef *cd = md->getClassDef();
if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface))
{
MemberContext *mc = new MemberContext(md);
@@ -4879,7 +4885,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
MemberDef *md=0;
for (mli.toFirst();(md=mli.current());++mli)
{
- ClassDef *cd = md->getClassDef();
+ const ClassDef *cd = md->getClassDef();
if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface)
{
MemberContext *mc = new MemberContext(md);
@@ -4976,7 +4982,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
if (!cache.sourceCodeParsed)
{
QCString codeFragment;
- FileDef *fd = m_memberDef->getBodyDef();
+ const FileDef *fd = m_memberDef->getBodyDef();
int startLine = m_memberDef->getStartBodyLine();
int endLine = m_memberDef->getEndBodyLine();
if (fd && readCodeFragment(fd->absFilePath(),
@@ -5271,7 +5277,7 @@ TemplateVariant MemberContext::get(const char *n) const
class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
{
public:
- Private(GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd)
+ Private(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd)
{
static bool init=FALSE;
if (!init)
@@ -5416,7 +5422,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getSubGroups())
{
GroupListIterator gli(*m_groupDef->getSubGroups());
- GroupDef *gd;
+ const GroupDef *gd;
for (gli.toFirst();(gd=gli.current());++gli)
{
if (gd->isVisible())
@@ -5438,7 +5444,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getExamples())
{
PageSDict::Iterator eli(*m_groupDef->getExamples());
- PageDef *ex;
+ const PageDef *ex;
for (eli.toFirst();(ex=eli.current());++eli)
{
exampleList->append(PageContext::alloc(ex,FALSE,TRUE));
@@ -5457,7 +5463,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getExamples())
{
PageSDict::Iterator eli(*m_groupDef->getPages());
- PageDef *ex;
+ const PageDef *ex;
for (eli.toFirst();(ex=eli.current());++eli)
{
pageList->append(PageContext::alloc(ex,FALSE,TRUE));
@@ -5476,7 +5482,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getDirs())
{
QListIterator<DirDef> it(*m_groupDef->getDirs());
- DirDef *dd;
+ const DirDef *dd;
for (it.toFirst();(dd=it.current());++it)
{
dirList->append(DirContext::alloc(dd));
@@ -5495,7 +5501,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getFiles())
{
QListIterator<FileDef> it(*m_groupDef->getFiles());
- FileDef *fd;
+ const FileDef *fd;
for (it.toFirst();(fd=it.current());++it)
{
fileList->append(FileContext::alloc(fd));
@@ -5514,7 +5520,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getClasses())
{
ClassSDict::Iterator sdi(*m_groupDef->getClasses());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->visibleInParentsDeclList())
@@ -5536,7 +5542,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getNamespaces())
{
NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces());
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (sdi.toFirst();(nd=sdi.current());++sdi)
{
if (nd->isLinkable() && !nd->isConstantGroup())
@@ -5730,7 +5736,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
if (m_groupDef->getClasses())
{
ClassSDict::Iterator sdi(*m_groupDef->getClasses());
- ClassDef *cd;
+ const ClassDef *cd;
for (sdi.toFirst();(cd=sdi.current());++sdi)
{
if (cd->name().find('@')==-1 &&
@@ -5751,10 +5757,10 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
return "module"; //theTranslator->trGroup(FALSE,TRUE);
}
private:
- GroupDef *m_groupDef;
+ const GroupDef *m_groupDef;
struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable
{
- Cachable(GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {}
+ Cachable(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {}
SharedPtr<TemplateList> modules;
SharedPtr<TemplateList> dirs;
SharedPtr<TemplateList> files;
@@ -5805,7 +5811,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
PropertyMapper<ModuleContext::Private> ModuleContext::Private::s_inst;
-ModuleContext::ModuleContext(GroupDef *gd) : RefCountedContext("ModuleContext")
+ModuleContext::ModuleContext(const GroupDef *gd) : RefCountedContext("ModuleContext")
{
p = new Private(gd);
}
@@ -5829,7 +5835,7 @@ class ClassListContext::Private : public GenericNodeListContext
void addClasses(const ClassSDict &classSDict)
{
ClassSDict::Iterator cli(classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
{
if (cd->getLanguage()==SrcLangExt_VHDL &&
@@ -5908,7 +5914,7 @@ class ClassIndexContext::Private
if (Doxygen::classSDict)
{
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst() ; (cd=cli.current()) ; ++cli )
{
if (cd->getLanguage()==SrcLangExt_VHDL &&
@@ -6216,7 +6222,7 @@ class NestingNodeContext::Private
{
public:
Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode,
- Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper)
+ const Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper)
: m_parent(parent), m_def(d), m_level(level), m_index(index)
{
m_children.reset(NestingContext::alloc(thisNode,level+1));
@@ -6278,7 +6284,7 @@ class NestingNodeContext::Private
{
if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass)
{
- m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<ClassDef*>(m_def)));
+ m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<const ClassDef*>(m_def)));
}
if (m_cache.classContext)
{
@@ -6293,7 +6299,7 @@ class NestingNodeContext::Private
{
if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace)
{
- m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<NamespaceDef*>(m_def)));
+ m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<const NamespaceDef*>(m_def)));
}
if (m_cache.namespaceContext)
{
@@ -6308,7 +6314,7 @@ class NestingNodeContext::Private
{
if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir)
{
- m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<DirDef*>(m_def)));
+ m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<const DirDef*>(m_def)));
}
if (m_cache.dirContext)
{
@@ -6323,7 +6329,7 @@ class NestingNodeContext::Private
{
if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile)
{
- m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<FileDef*>(m_def)));
+ m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<const FileDef*>(m_def)));
}
if (m_cache.fileContext)
{
@@ -6338,7 +6344,7 @@ class NestingNodeContext::Private
{
if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage)
{
- m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<PageDef*>(m_def),FALSE,FALSE));
+ m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<const PageDef*>(m_def),FALSE,FALSE));
}
if (m_cache.pageContext)
{
@@ -6353,7 +6359,7 @@ class NestingNodeContext::Private
{
if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup)
{
- m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<GroupDef*>(m_def)));
+ m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<const GroupDef*>(m_def)));
}
if (m_cache.moduleContext)
{
@@ -6425,7 +6431,7 @@ class NestingNodeContext::Private
void addClasses(bool inherit, bool hideSuper)
{
- ClassDef *cd = dynamic_cast<ClassDef*>(m_def);
+ const ClassDef *cd = dynamic_cast<const ClassDef*>(m_def);
if (cd && inherit)
{
bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd);
@@ -6453,7 +6459,7 @@ class NestingNodeContext::Private
}
void addNamespaces(bool addClasses)
{
- NamespaceDef *nd = dynamic_cast<NamespaceDef*>(m_def);
+ const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(m_def);
if (nd && nd->getNamespaceSDict())
{
m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses);
@@ -6465,7 +6471,7 @@ class NestingNodeContext::Private
}
void addDirFiles()
{
- DirDef *dd = dynamic_cast<DirDef*>(m_def);
+ const DirDef *dd = dynamic_cast<const DirDef*>(m_def);
if (dd)
{
m_children->addDirs(dd->subDirs());
@@ -6477,7 +6483,7 @@ class NestingNodeContext::Private
}
void addPages()
{
- PageDef *pd = dynamic_cast<PageDef*>(m_def);
+ const PageDef *pd = dynamic_cast<const PageDef*>(m_def);
if (pd && pd->getSubPages())
{
m_children->addPages(*pd->getSubPages(),FALSE);
@@ -6485,7 +6491,7 @@ class NestingNodeContext::Private
}
void addModules()
{
- GroupDef *gd = dynamic_cast<GroupDef*>(m_def);
+ const GroupDef *gd = dynamic_cast<const GroupDef*>(m_def);
if (gd && gd->getSubGroups())
{
m_children->addModules(*gd->getSubGroups());
@@ -6493,7 +6499,7 @@ class NestingNodeContext::Private
}
private:
const NestingNodeContext *m_parent;
- Definition *m_def;
+ const Definition *m_def;
SharedPtr<NestingContext> m_children;
int m_level;
int m_index;
@@ -6515,7 +6521,7 @@ class NestingNodeContext::Private
PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst;
NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent,
- Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper)
+ const Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper)
: RefCountedContext("NestingNodeContext")
{
p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper);
@@ -6548,7 +6554,7 @@ class NestingContext::Private : public GenericNodeListContext
void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses)
{
NamespaceSDict::Iterator nli(nsDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
if (nd->localName().find('@')==-1 &&
@@ -6568,7 +6574,7 @@ class NestingContext::Private : public GenericNodeListContext
void addClasses(const ClassSDict &clDict,bool rootOnly)
{
ClassSDict::Iterator cli(clDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (;(cd=cli.current());++cli)
{
if (cd->getLanguage()==SrcLangExt_VHDL)
@@ -6597,7 +6603,7 @@ class NestingContext::Private : public GenericNodeListContext
void addDirs(const DirSDict &dirDict)
{
SDict<DirDef>::Iterator dli(dirDict);
- DirDef *dd;
+ const DirDef *dd;
for (dli.toFirst();(dd=dli.current());++dli)
{
if (dd->getOuterScope()==Doxygen::globalScope)
@@ -6610,7 +6616,7 @@ class NestingContext::Private : public GenericNodeListContext
void addDirs(const DirList &dirList)
{
QListIterator<DirDef> li(dirList);
- DirDef *dd;
+ const DirDef *dd;
for (li.toFirst();(dd=li.current());++li)
{
append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE));
@@ -6624,7 +6630,7 @@ class NestingContext::Private : public GenericNodeListContext
for (fnli.toFirst();(fn=fnli.current());++fnli)
{
FileNameIterator fni(*fn);
- FileDef *fd;
+ const FileDef *fd;
for (;(fd=fni.current());++fni)
{
if (fd->getDirDef()==0) // top level file
@@ -6638,7 +6644,7 @@ class NestingContext::Private : public GenericNodeListContext
void addFiles(const FileList &fList)
{
QListIterator<FileDef> li(fList);
- FileDef *fd;
+ const FileDef *fd;
for (li.toFirst();(fd=li.current());++li)
{
append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE));
@@ -6648,7 +6654,7 @@ class NestingContext::Private : public GenericNodeListContext
void addPages(const PageSDict &pages,bool rootOnly)
{
SDict<PageDef>::Iterator pli(pages);
- PageDef *pd;
+ const PageDef *pd;
for (pli.toFirst();(pd=pli.current());++pli)
{
if (!rootOnly ||
@@ -6663,7 +6669,7 @@ class NestingContext::Private : public GenericNodeListContext
void addModules(const GroupSDict &groups)
{
GroupSDict::Iterator gli(groups);
- GroupDef *gd;
+ const GroupDef *gd;
for (gli.toFirst();(gd=gli.current());++gli)
{
static bool externalGroups = Config_getBool(EXTERNAL_GROUPS);
@@ -6679,7 +6685,7 @@ class NestingContext::Private : public GenericNodeListContext
void addModules(const GroupList &list)
{
GroupListIterator gli(list);
- GroupDef *gd;
+ const GroupDef *gd;
for (gli.toFirst();(gd=gli.current());++gli)
{
if (gd->isVisible())
@@ -6696,7 +6702,7 @@ class NestingContext::Private : public GenericNodeListContext
BaseClassDef *bcd;
for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli)
{
- ClassDef *cd=bcd->classDef;
+ const ClassDef *cd=bcd->classDef;
if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS)
{
continue;
@@ -6723,7 +6729,7 @@ class NestingContext::Private : public GenericNodeListContext
void addClassHierarchy(const ClassSDict &classSDict,bool)
{
ClassSDict::Iterator cli(classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
bool b;
@@ -6973,7 +6979,7 @@ class NamespaceListContext::Private : public GenericNodeListContext
void addNamespaces(const NamespaceSDict &nsDict)
{
NamespaceSDict::Iterator nli(nsDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
if (nd->isLinkableInProject())
@@ -7148,7 +7154,7 @@ class FileListContext::Private : public GenericNodeListContext
for (fnli.toFirst();(fn=fnli.current());++fnli)
{
FileNameIterator fni(*fn);
- FileDef *fd;
+ const FileDef *fd;
for (fni.toFirst();(fd=fni.current());++fni)
{
bool doc = fd->isLinkableInProject();
@@ -7198,7 +7204,7 @@ class DirListContext::Private : public GenericNodeListContext
public:
Private()
{
- DirDef *dir;
+ const DirDef *dir;
DirSDict::Iterator sdi(*Doxygen::directories);
for (sdi.toFirst();(dir=sdi.current());++sdi)
{
@@ -7240,19 +7246,19 @@ TemplateListIntf::ConstIterator *DirListContext::createIterator() const
class UsedFilesContext::Private : public GenericNodeListContext
{
public:
- void addFile(FileDef *fd)
+ void addFile(const FileDef *fd)
{
append(FileContext::alloc(fd));
}
};
-UsedFilesContext::UsedFilesContext(ClassDef *cd) : RefCountedContext("UsedFilesContext")
+UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("UsedFilesContext")
{
p = new Private;
if (cd)
{
QListIterator<FileDef> li(cd->usedFiles());
- FileDef *fd;
+ const FileDef *fd;
for (li.toFirst();(fd=li.current());++li)
{
p->addFile(fd);
@@ -7281,7 +7287,7 @@ TemplateListIntf::ConstIterator *UsedFilesContext::createIterator() const
return p->createIterator();
}
-void UsedFilesContext::addFile(FileDef *fd)
+void UsedFilesContext::addFile(const FileDef *fd)
{
p->addFile(fd);
}
@@ -7518,7 +7524,7 @@ class PageListContext::Private : public GenericNodeListContext
void addPages(const PageSDict &pages)
{
PageSDict::Iterator pdi(pages);
- PageDef *pd=0;
+ const PageDef *pd=0;
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
if (!pd->getGroupDef() && !pd->isReference())
@@ -7567,7 +7573,7 @@ class ExampleListContext::Private : public GenericNodeListContext
if (Doxygen::exampleSDict)
{
PageSDict::Iterator pdi(*Doxygen::exampleSDict);
- PageDef *pd=0;
+ const PageDef *pd=0;
for (pdi.toFirst();(pd=pdi.current());++pdi)
{
if (!pd->getGroupDef() && !pd->isReference())
@@ -7614,7 +7620,7 @@ class ModuleListContext::Private : public GenericNodeListContext
void addModules()
{
GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
+ const GroupDef *gd;
for (gli.toFirst();(gd=gli.current());++gli)
{
if (!gd->isReference())
@@ -7769,7 +7775,7 @@ TemplateVariant ModuleTreeContext::get(const char *name) const
class NavPathElemContext::Private
{
public:
- Private(Definition *def) : m_def(def)
+ Private(const Definition *def) : m_def(def)
{
static bool init=FALSE;
if (!init)
@@ -7834,14 +7840,14 @@ class NavPathElemContext::Private
return m_def->externalReference(relPathAsString());
}
private:
- Definition *m_def;
+ const Definition *m_def;
static PropertyMapper<NavPathElemContext::Private> s_inst;
};
//%% }
PropertyMapper<NavPathElemContext::Private> NavPathElemContext::Private::s_inst;
-NavPathElemContext::NavPathElemContext(Definition *def) : RefCountedContext("NavPathElemContext")
+NavPathElemContext::NavPathElemContext(const Definition *def) : RefCountedContext("NavPathElemContext")
{
p = new Private(def);
}
@@ -8014,7 +8020,7 @@ class GlobalsIndexContext::Private
MemberNameIterator mni(*mn);
for (mni.toFirst();(md=mni.current());++mni)
{
- FileDef *fd=md->getFileDef();
+ const FileDef *fd=md->getFileDef();
if (fd && fd->isLinkableInProject() &&
!md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject())
{
@@ -8171,7 +8177,7 @@ class ClassMembersIndexContext::Private
MemberNameIterator mni(*mn);
for (mni.toFirst();(md=mni.current());++mni)
{
- ClassDef *cd = md->getClassDef();
+ const ClassDef *cd = md->getClassDef();
if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 &&
md->isLinkableInProject() && !md->name().isEmpty())
{
@@ -8330,7 +8336,7 @@ class NamespaceMembersIndexContext::Private
MemberNameIterator mni(*mn);
for (mni.toFirst();(md=mni.current());++mni)
{
- NamespaceDef *nd=md->getNamespaceDef();
+ const NamespaceDef *nd=md->getNamespaceDef();
if (nd && nd->isLinkableInProject() &&
!md->name().isEmpty() && md->isLinkableInProject())
{
@@ -8508,7 +8514,7 @@ TemplateVariant InheritanceGraphContext::get(const char *name) const
class InheritanceNodeContext::Private
{
public:
- Private(ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name)
+ Private(const ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name)
{
static bool init=FALSE;
if (!init)
@@ -8535,7 +8541,7 @@ class InheritanceNodeContext::Private
return m_name;
}
private:
- ClassDef *m_classDef;
+ const ClassDef *m_classDef;
mutable SharedPtr<ClassContext> m_classContext;
QCString m_name;
static PropertyMapper<InheritanceNodeContext::Private> s_inst;
@@ -8544,7 +8550,7 @@ class InheritanceNodeContext::Private
PropertyMapper<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst;
-InheritanceNodeContext::InheritanceNodeContext(ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext")
+InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext")
{
p = new Private(cd,name);
}
@@ -8565,7 +8571,7 @@ TemplateVariant InheritanceNodeContext::get(const char *name) const
class InheritanceListContext::Private : public GenericNodeListContext
{
public:
- void addClass(ClassDef *cd,const QCString &name)
+ void addClass(const ClassDef *cd,const QCString &name)
{
append(InheritanceNodeContext::alloc(cd,name));
}
@@ -8580,7 +8586,7 @@ InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool b
BaseClassDef *bcd;
for (li.toFirst();(bcd=li.current());++li)
{
- ClassDef *cd=bcd->classDef;
+ const ClassDef *cd=bcd->classDef;
QCString name;
if (baseClasses)
{
@@ -8806,7 +8812,7 @@ class AllMembersListContext::Private : public GenericNodeListContext
for (mnii2.toFirst();(mi=mnii2.current());++mnii2)
{
MemberDef *md=mi->memberDef;
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
if (cd && !md->name().isEmpty() && md->name()[0]!='@')
{
if ((cd->isLinkable() && md->isLinkable()) ||
@@ -8862,7 +8868,7 @@ TemplateListIntf::ConstIterator *AllMembersListContext::createIterator() const
class MemberGroupInfoContext::Private
{
public:
- Private(Definition *def,const QCString &relPath,const MemberGroup *mg) :
+ Private(const Definition *def,const QCString &relPath,const MemberGroup *mg) :
m_def(def),
m_relPath(relPath),
m_memberGroup(mg)
@@ -8936,7 +8942,7 @@ class MemberGroupInfoContext::Private
return FALSE;
}
private:
- Definition *m_def;
+ const Definition *m_def;
QCString m_relPath;
const MemberGroup *m_memberGroup;
struct Cachable
@@ -8952,7 +8958,7 @@ class MemberGroupInfoContext::Private
PropertyMapper<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst;
-MemberGroupInfoContext::MemberGroupInfoContext(Definition *def,
+MemberGroupInfoContext::MemberGroupInfoContext(const Definition *def,
const QCString &relPath,const MemberGroup *mg) : RefCountedContext("MemberGroupInfoContext")
{
p = new Private(def,relPath,mg);
@@ -8974,7 +8980,7 @@ TemplateVariant MemberGroupInfoContext::get(const char *name) const
class MemberGroupListContext::Private : public GenericNodeListContext
{
public:
- void addMemberGroup(Definition *def,const QCString &relPath,const MemberGroup *mg)
+ void addMemberGroup(const Definition *def,const QCString &relPath,const MemberGroup *mg)
{
append(MemberGroupInfoContext::alloc(def,relPath,mg));
}
@@ -8985,7 +8991,7 @@ MemberGroupListContext::MemberGroupListContext() : RefCountedContext("MemberGrou
p = new Private;
}
-MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupList *list) : RefCountedContext("MemberGroupListContext")
+MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList *list) : RefCountedContext("MemberGroupListContext")
{
p = new Private;
if (list)
@@ -8999,7 +9005,7 @@ MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &r
}
}
-MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) : RefCountedContext("MemberGroupListContext")
+MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) : RefCountedContext("MemberGroupListContext")
{
p = new Private;
if (dict)
@@ -9045,7 +9051,7 @@ TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const
class MemberListInfoContext::Private
{
public:
- Private(Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) :
+ Private(const Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) :
m_def(def),
m_memberList(ml),
m_relPath(relPath),
@@ -9102,7 +9108,7 @@ class MemberListInfoContext::Private
m_def->definitionType()==Definition::TypeClass)
{
InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc();
- ctx->addMemberList(dynamic_cast<ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE);
+ ctx->addMemberList(dynamic_cast<const ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE);
m_cache.inherited.reset(ctx);
}
if (m_cache.inherited)
@@ -9115,7 +9121,7 @@ class MemberListInfoContext::Private
}
}
private:
- Definition *m_def;
+ const Definition *m_def;
const MemberList *m_memberList;
QCString m_relPath;
QCString m_title;
@@ -9134,7 +9140,7 @@ class MemberListInfoContext::Private
PropertyMapper<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst;
MemberListInfoContext::MemberListInfoContext(
- Definition *def,const QCString &relPath,const MemberList *ml,
+ const Definition *def,const QCString &relPath,const MemberList *ml,
const QCString &title,const QCString &subtitle) : RefCountedContext("MemberListInfoContext")
{
p = new Private(def,relPath,ml,title,subtitle);
@@ -9157,7 +9163,7 @@ TemplateVariant MemberListInfoContext::get(const char *name) const
class InheritedMemberInfoContext::Private
{
public:
- Private(ClassDef *cd,MemberList *ml,const QCString &title)
+ Private(const ClassDef *cd,MemberList *ml,const QCString &title)
: m_class(cd), m_memberList(ml), m_title(title)
{
static bool init=FALSE;
@@ -9216,7 +9222,7 @@ class InheritedMemberInfoContext::Private
}
private:
- ClassDef * m_class;
+ const ClassDef * m_class;
MemberList *m_memberList;
QCString m_title;
mutable SharedPtr<ClassContext> m_classCtx;
@@ -9228,7 +9234,7 @@ class InheritedMemberInfoContext::Private
PropertyMapper<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst;
-InheritedMemberInfoContext::InheritedMemberInfoContext(ClassDef *cd,MemberList *ml,
+InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,MemberList *ml,
const QCString &title) : RefCountedContext("InheritedMemberInfoContext")
{
p = new Private(cd,ml,title);
@@ -9250,7 +9256,7 @@ TemplateVariant InheritedMemberInfoContext::get(const char *name) const
class InheritedMemberInfoListContext::Private : public GenericNodeListContext
{
public:
- void addMemberList(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
+ void addMemberList(const ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
{
if (ml)
{
@@ -9265,7 +9271,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
}
}
}
- void addMemberListIncludingGrouped(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
+ void addMemberListIncludingGrouped(const ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList)
{
if (ml)
{
@@ -9281,8 +9287,8 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
}
}
}
- void addMemberGroupsOfClass(ClassDef *inheritedFrom,
- ClassDef *cd,MemberListType lt,MemberList *combinedList)
+ void addMemberGroupsOfClass(const ClassDef *inheritedFrom,
+ const ClassDef *cd,MemberListType lt,MemberList *combinedList)
{
if (cd->getMemberGroupSDict())
{
@@ -9307,7 +9313,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
}
}
}
- void addInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt,
+ void addInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt,
MemberListType lt1,int lt2,const QCString &title,bool additionalList)
{
int count = cd->countMembersIncludingGrouped(lt1,inheritedFrom,additionalList);
@@ -9324,7 +9330,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext
append(InheritedMemberInfoContext::alloc(cd,combinedList,title));
}
}
- void findInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt,
+ void findInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt,
int lt2, const QCString &title,bool additionalList,
QPtrDict<void> *visitedClasses)
{
@@ -9366,7 +9372,7 @@ InheritedMemberInfoListContext::InheritedMemberInfoListContext() : RefCountedCon
}
void InheritedMemberInfoListContext::addMemberList(
- ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList)
+ const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList)
{
QPtrDict<void> visited(17);
bool memberInSection = cd->countMembersIncludingGrouped(lt,cd,FALSE)>0;
@@ -9407,7 +9413,7 @@ TemplateListIntf::ConstIterator *InheritedMemberInfoListContext::createIterator(
class ArgumentContext::Private
{
public:
- Private(const Argument *arg,Definition *def,const QCString &relPath) :
+ Private(const Argument *arg,const Definition *def,const QCString &relPath) :
m_argument(arg), m_def(def), m_relPath(relPath)
{
static bool init=FALSE;
@@ -9477,7 +9483,7 @@ class ArgumentContext::Private
}
private:
const Argument *m_argument;
- Definition *m_def;
+ const Definition *m_def;
QCString m_relPath;
struct Cachable
{
@@ -9490,7 +9496,7 @@ class ArgumentContext::Private
PropertyMapper<ArgumentContext::Private> ArgumentContext::Private::s_inst;
-ArgumentContext::ArgumentContext(const Argument *al,Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext")
+ArgumentContext::ArgumentContext(const Argument *al,const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext")
{
p = new Private(al,def,relPath);
}
@@ -9511,7 +9517,7 @@ TemplateVariant ArgumentContext::get(const char *name) const
class ArgumentListContext::Private : public GenericNodeListContext
{
public:
- void addArgument(const Argument *arg,Definition *def,const QCString &relPath)
+ void addArgument(const Argument *arg,const Definition *def,const QCString &relPath)
{
append(ArgumentContext::alloc(arg,def,relPath));
}
@@ -9523,7 +9529,7 @@ ArgumentListContext::ArgumentListContext() : RefCountedContext("ArgumentListCont
}
ArgumentListContext::ArgumentListContext(const ArgumentList *list,
- Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext")
+ const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext")
{
p = new Private;
if (list)
@@ -9645,7 +9651,7 @@ class SymbolContext::Private
{
if (md)
{
- FileDef *fd = md->getBodyDef();
+ const FileDef *fd = md->getBodyDef();
if (fd==0) fd = md->getFileDef();
if (fd)
{
@@ -9713,8 +9719,8 @@ class SymbolListContext::Private : public GenericNodeListContext
Private(const SearchDefinitionList *sdl)
{
QListIterator<Definition> li(*sdl);
- Definition *def;
- Definition *prev = 0;
+ const Definition *def;
+ const Definition *prev = 0;
for (li.toFirst();(def=li.current());)
{
++li;
@@ -10364,13 +10370,13 @@ void generateOutputViaTemplate()
// clear all cached data in Definition objects.
QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
- DefinitionIntf *intf;
+ const DefinitionIntf *intf;
for (;(intf=di.current());++di)
{
if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
{
- DefinitionListIterator dli(*(DefinitionList*)intf);
- Definition *d;
+ DefinitionListIterator dli(*dynamic_cast<const DefinitionList*>(intf));
+ const Definition *d;
// for each symbol
for (dli.toFirst();(d=dli.current());++dli)
{
@@ -10379,7 +10385,7 @@ void generateOutputViaTemplate()
}
else // single symbol
{
- Definition *d = (Definition *)intf;
+ const Definition *d = dynamic_cast<const Definition *>(intf);
d->setCookie(0);
}
}
diff --git a/src/context.h b/src/context.h
index e082c4b..ecd1227 100644
--- a/src/context.h
+++ b/src/context.h
@@ -186,7 +186,7 @@ class TranslateContext : public RefCountedContext, public TemplateStructIntf
class UsedFilesContext : public RefCountedContext, public TemplateListIntf
{
public:
- static UsedFilesContext *alloc(ClassDef *cd) { return new UsedFilesContext(cd); }
+ static UsedFilesContext *alloc(const ClassDef *cd) { return new UsedFilesContext(cd); }
// TemplateListIntf
virtual int count() const;
@@ -195,10 +195,10 @@ class UsedFilesContext : public RefCountedContext, public TemplateListIntf
virtual int addRef() { return RefCountedContext::addRef(); }
virtual int release() { return RefCountedContext::release(); }
- void addFile(FileDef *fd);
+ void addFile(const FileDef *fd);
private:
- UsedFilesContext(ClassDef *cd);
+ UsedFilesContext(const ClassDef *cd);
~UsedFilesContext();
class Private;
@@ -253,7 +253,7 @@ class IncludeInfoListContext : public RefCountedContext, public TemplateListIntf
class ClassContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static ClassContext *alloc(ClassDef *cd) { return new ClassContext(cd); }
+ static ClassContext *alloc(const ClassDef *cd) { return new ClassContext(cd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -261,7 +261,7 @@ class ClassContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- ClassContext(ClassDef *);
+ ClassContext(const ClassDef *);
~ClassContext();
class Private;
Private *p;
@@ -272,7 +272,7 @@ class ClassContext : public RefCountedContext, public TemplateStructIntf
class NamespaceContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static NamespaceContext *alloc(NamespaceDef *nd) { return new NamespaceContext(nd); }
+ static NamespaceContext *alloc(const NamespaceDef *nd) { return new NamespaceContext(nd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -280,7 +280,7 @@ class NamespaceContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- NamespaceContext(NamespaceDef *);
+ NamespaceContext(const NamespaceDef *);
~NamespaceContext();
class Private;
Private *p;
@@ -291,7 +291,7 @@ class NamespaceContext : public RefCountedContext, public TemplateStructIntf
class FileContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static FileContext *alloc(FileDef *fd) { return new FileContext(fd); }
+ static FileContext *alloc(const FileDef *fd) { return new FileContext(fd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -299,7 +299,7 @@ class FileContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- FileContext(FileDef *);
+ FileContext(const FileDef *);
~FileContext();
class Private;
Private *p;
@@ -309,7 +309,7 @@ class FileContext : public RefCountedContext, public TemplateStructIntf
class DirContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static DirContext *alloc(DirDef *dd) { return new DirContext(dd); }
+ static DirContext *alloc(const DirDef *dd) { return new DirContext(dd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -317,7 +317,7 @@ class DirContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- DirContext(DirDef *);
+ DirContext(const DirDef *);
~DirContext();
class Private;
Private *p;
@@ -329,7 +329,7 @@ class DirContext : public RefCountedContext, public TemplateStructIntf
class PageContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static PageContext *alloc(PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); }
+ static PageContext *alloc(const PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -337,7 +337,7 @@ class PageContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- PageContext(PageDef *,bool isMainPage,bool isExample);
+ PageContext(const PageDef *,bool isMainPage,bool isExample);
~PageContext();
class Private;
Private *p;
@@ -368,7 +368,7 @@ class MemberContext : public RefCountedContext, public TemplateStructIntf
class ModuleContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static ModuleContext *alloc(GroupDef *gd) { return new ModuleContext(gd); }
+ static ModuleContext *alloc(const GroupDef *gd) { return new ModuleContext(gd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -376,7 +376,7 @@ class ModuleContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- ModuleContext(GroupDef *);
+ ModuleContext(const GroupDef *);
~ModuleContext();
class Private;
Private *p;
@@ -447,7 +447,7 @@ class InheritanceGraphContext : public RefCountedContext, public TemplateStructI
class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static ClassInheritanceNodeContext *alloc(ClassDef *cd)
+ static ClassInheritanceNodeContext *alloc(const ClassDef *cd)
{ return new ClassInheritanceNodeContext(cd); }
// TemplateStructIntf methods
@@ -458,7 +458,7 @@ class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStr
void addChildren(const BaseClassList *bcl,bool hideSuper);
private:
- ClassInheritanceNodeContext(ClassDef *);
+ ClassInheritanceNodeContext(const ClassDef *);
~ClassInheritanceNodeContext();
class Private;
Private *p;
@@ -509,7 +509,7 @@ class ClassHierarchyContext : public RefCountedContext, public TemplateStructInt
class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static NestingNodeContext *alloc(const NestingNodeContext *parent,Definition *def,
+ static NestingNodeContext *alloc(const NestingNodeContext *parent,const Definition *def,
int index,int level,bool addClasses,bool inherit,bool hideSuper)
{ return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper); }
@@ -522,7 +522,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf
private:
NestingNodeContext(const NestingNodeContext *parent,
- Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper);
+ const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper);
~NestingNodeContext();
class Private;
Private *p;
@@ -729,7 +729,7 @@ class PageTreeContext : public RefCountedContext, public TemplateStructIntf
class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static ModuleNodeContext *alloc(GroupDef *gd) { return new ModuleNodeContext(gd); }
+ static ModuleNodeContext *alloc(const GroupDef *gd) { return new ModuleNodeContext(gd); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -737,7 +737,7 @@ class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- ModuleNodeContext(GroupDef *);
+ ModuleNodeContext(const GroupDef *);
~ModuleNodeContext();
class Private;
Private *p;
@@ -889,7 +889,7 @@ class NamespaceMembersIndexContext : public RefCountedContext, public TemplateSt
class NavPathElemContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static NavPathElemContext *alloc(Definition *def) { return new NavPathElemContext(def); }
+ static NavPathElemContext *alloc(const Definition *def) { return new NavPathElemContext(def); }
// TemplateStructIntf methods
virtual TemplateVariant get(const char *name) const;
@@ -897,7 +897,7 @@ class NavPathElemContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- NavPathElemContext(Definition *def);
+ NavPathElemContext(const Definition *def);
~NavPathElemContext();
class Private;
Private *p;
@@ -909,7 +909,7 @@ class NavPathElemContext : public RefCountedContext, public TemplateStructIntf
class InheritanceNodeContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static InheritanceNodeContext *alloc(ClassDef *cd,const QCString &name)
+ static InheritanceNodeContext *alloc(const ClassDef *cd,const QCString &name)
{ return new InheritanceNodeContext(cd,name); }
// TemplateStructIntf methods
@@ -918,7 +918,7 @@ class InheritanceNodeContext : public RefCountedContext, public TemplateStructIn
virtual int release() { return RefCountedContext::release(); }
private:
- InheritanceNodeContext(ClassDef *cd,const QCString &name);
+ InheritanceNodeContext(const ClassDef *cd,const QCString &name);
~InheritanceNodeContext();
class Private;
Private *p;
@@ -979,7 +979,7 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf
class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static MemberGroupInfoContext *alloc(Definition *def,const QCString &relPath,const MemberGroup *mg)
+ static MemberGroupInfoContext *alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg)
{ return new MemberGroupInfoContext(def,relPath,mg); }
// TemplateStructIntf methods
@@ -988,7 +988,7 @@ class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIn
virtual int release() { return RefCountedContext::release(); }
private:
- MemberGroupInfoContext(Definition *def,const QCString &relPath,const MemberGroup *mg);
+ MemberGroupInfoContext(const Definition *def,const QCString &relPath,const MemberGroup *mg);
~MemberGroupInfoContext();
class Private;
Private *p;
@@ -1001,9 +1001,9 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf
public:
static MemberGroupListContext *alloc()
{ return new MemberGroupListContext; }
- static MemberGroupListContext *alloc(Definition *def,const QCString &relPath,const MemberGroupList *list)
+ static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupList *list)
{ return new MemberGroupListContext(def,relPath,list); }
- static MemberGroupListContext *alloc(Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping)
+ static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping)
{ return new MemberGroupListContext(def,relPath,dict,subGrouping); }
// TemplateListIntf
@@ -1015,8 +1015,8 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf
private:
MemberGroupListContext();
- MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupList *list);
- MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupSDict *mgDict,bool subGrouping);
+ MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList *list);
+ MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupSDict *mgDict,bool subGrouping);
~MemberGroupListContext();
class Private;
Private *p;
@@ -1028,7 +1028,7 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf
class MemberListInfoContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static MemberListInfoContext *alloc(Definition *def,const QCString &relPath,
+ static MemberListInfoContext *alloc(const Definition *def,const QCString &relPath,
const MemberList *ml,const QCString &title,
const QCString &subtitle=QCString())
{ return new MemberListInfoContext(def,relPath,ml,title,subtitle); }
@@ -1039,7 +1039,7 @@ class MemberListInfoContext : public RefCountedContext, public TemplateStructInt
virtual int release() { return RefCountedContext::release(); }
private:
- MemberListInfoContext(Definition *def,const QCString &relPath,
+ MemberListInfoContext(const Definition *def,const QCString &relPath,
const MemberList *ml,const QCString &title,
const QCString &subtitle=QCString());
~MemberListInfoContext();
@@ -1071,7 +1071,7 @@ class MemberInfoContext : public RefCountedContext, public TemplateStructIntf
class InheritedMemberInfoContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static InheritedMemberInfoContext *alloc(ClassDef *cd,MemberList *ml,const QCString &title)
+ static InheritedMemberInfoContext *alloc(const ClassDef *cd,MemberList *ml,const QCString &title)
{ return new InheritedMemberInfoContext(cd,ml,title); }
// TemplateStructIntf methods
@@ -1080,7 +1080,7 @@ class InheritedMemberInfoContext : public RefCountedContext, public TemplateStru
virtual int release() { return RefCountedContext::release(); }
private:
- InheritedMemberInfoContext(ClassDef *cd,MemberList *ml,const QCString &title);
+ InheritedMemberInfoContext(const ClassDef *cd,MemberList *ml,const QCString &title);
~InheritedMemberInfoContext();
class Private;
Private *p;
@@ -1092,7 +1092,7 @@ class InheritedMemberInfoListContext : public RefCountedContext, public Template
{
public:
static InheritedMemberInfoListContext *alloc() { return new InheritedMemberInfoListContext; }
- void addMemberList(ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE);
+ void addMemberList(const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE);
// TemplateListIntf
virtual int count() const;
@@ -1138,7 +1138,7 @@ class AllMembersListContext : public RefCountedContext, public TemplateListIntf
class ArgumentContext : public RefCountedContext, public TemplateStructIntf
{
public:
- static ArgumentContext *alloc(const Argument *arg,Definition *def,const QCString &relPath)
+ static ArgumentContext *alloc(const Argument *arg,const Definition *def,const QCString &relPath)
{ return new ArgumentContext(arg,def,relPath); }
// TemplateStructIntf methods
@@ -1147,7 +1147,7 @@ class ArgumentContext : public RefCountedContext, public TemplateStructIntf
virtual int release() { return RefCountedContext::release(); }
private:
- ArgumentContext(const Argument *arg,Definition *def,const QCString &relPath);
+ ArgumentContext(const Argument *arg,const Definition *def,const QCString &relPath);
~ArgumentContext();
class Private;
Private *p;
@@ -1159,7 +1159,7 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf
{
public:
static ArgumentListContext *alloc() { return new ArgumentListContext; }
- static ArgumentListContext *alloc(const ArgumentList *al,Definition *def,const QCString &relPath)
+ static ArgumentListContext *alloc(const ArgumentList *al,const Definition *def,const QCString &relPath)
{ return new ArgumentListContext(al,def,relPath); }
// TemplateListIntf
@@ -1171,7 +1171,7 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf
private:
ArgumentListContext();
- ArgumentListContext(const ArgumentList *al,Definition *def,const QCString &relPath);
+ ArgumentListContext(const ArgumentList *al,const Definition *def,const QCString &relPath);
~ArgumentListContext();
class Private;
Private *p;
diff --git a/src/cppvalue.cpp b/src/cppvalue.cpp
index 176931d..1543498 100644
--- a/src/cppvalue.cpp
+++ b/src/cppvalue.cpp
@@ -21,44 +21,44 @@
#include "cppvalue.h"
#include "constexp.h"
-CPPValue parseOctal()
+CPPValue parseOctal(const QCString& token)
{
long val = 0;
- for (const char *p = g_strToken.data(); *p != 0; p++)
+ for (const char *p = token.data(); *p != 0; p++)
{
if (*p >= '0' && *p <= '7') val = val * 8 + *p - '0';
}
return CPPValue(val);
}
-CPPValue parseDecimal()
+CPPValue parseDecimal(const QCString& token)
{
long val = 0;
- for (const char *p = g_strToken.data(); *p != 0; p++)
+ for (const char *p = token.data(); *p != 0; p++)
{
if (*p >= '0' && *p <= '9') val = val * 10 + *p - '0';
}
return CPPValue(val);
}
-CPPValue parseHexadecimal()
+CPPValue parseHexadecimal(const QCString& token)
{
long val = 0;
- for (const char *p = g_strToken.data(); *p != 0; p++)
+ for (const char *p = token.data(); *p != 0; p++)
{
if (*p >= '0' && *p <= '9') val = val * 16 + *p - '0';
else if (*p >= 'a' && *p <= 'f') val = val * 16 + *p - 'a' + 10;
else if (*p >= 'A' && *p <= 'F') val = val * 16 + *p - 'A' + 10;
}
- //printf("parseHexadecimal %s->%x\n",g_strToken.data(),val);
+ //printf("parseHexadecimal %s->%x\n",token.data(),val);
return CPPValue(val);
}
-CPPValue parseCharacter() // does not work for '\n' and the alike
+CPPValue parseCharacter(const QCString& token) // does not work for '\n' and the alike
{
- if (g_strToken[1]=='\\')
+ if (token[1]=='\\')
{
- switch(g_strToken[2])
+ switch(token[2])
{
case 'n': return CPPValue((long)'\n');
case 't': return CPPValue((long)'\t');
@@ -79,17 +79,17 @@ CPPValue parseCharacter() // does not work for '\n' and the alike
case '5': // fall through
case '6': // fall through
case '7': // fall through
- return parseOctal();
+ return parseOctal(token);
case 'x':
- case 'X': return parseHexadecimal();
- default: printf("Invalid escape sequence %s found!\n",g_strToken.data());
+ case 'X': return parseHexadecimal(token);
+ default: printf("Invalid escape sequence %s found!\n",token.data());
return CPPValue(0L);
}
}
- return CPPValue((long)g_strToken[1]);
+ return CPPValue((long)token[1]);
}
-CPPValue parseFloat()
+CPPValue parseFloat(const QCString& token)
{
- return CPPValue(atof(g_strToken));
+ return CPPValue(atof(token));
}
diff --git a/src/cppvalue.h b/src/cppvalue.h
index 59dd594..cde033d 100644
--- a/src/cppvalue.h
+++ b/src/cppvalue.h
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <qglobal.h>
+#include <qcstring.h>
/** A class representing a C-preprocessor value. */
class CPPValue
@@ -52,10 +53,10 @@ class CPPValue
} v;
};
-extern CPPValue parseOctal();
-extern CPPValue parseDecimal();
-extern CPPValue parseHexadecimal();
-extern CPPValue parseCharacter();
-extern CPPValue parseFloat();
+extern CPPValue parseOctal(const QCString& token);
+extern CPPValue parseDecimal(const QCString& token);
+extern CPPValue parseHexadecimal(const QCString& token);
+extern CPPValue parseCharacter(const QCString& token);
+extern CPPValue parseFloat(const QCString& token);
#endif
diff --git a/src/declinfo.l b/src/declinfo.l
index a91f832..d7f8743 100644
--- a/src/declinfo.l
+++ b/src/declinfo.l
@@ -16,6 +16,10 @@
*/
%option never-interactive
%option prefix="declinfoYY"
+%option nounput
+%option noyywrap
+%option reentrant
+%option extra-type="struct declinfoYY_state *"
%{
@@ -33,79 +37,43 @@
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 1
+#define YY_NEVER_INTERACTIVE 1
/* -----------------------------------------------------------------
*
* statics
*/
-
-static const char * inputString;
-static int inputPosition;
-static QCString scope;
-static QCString className;
-static QCString classTempList;
-static QCString funcTempList;
-static QCString type;
-static QCString name;
-static QCString args;
-static int sharpCount;
-static bool classTempListFound;
-static bool funcTempListFound;
-static QCString exceptionString;
-static bool insideObjC;
-
-static void addType()
-{
- //printf("addType() type=`%s' scope=`%s' name=`%s'\n",
- // type.data(),scope.data(),name.data());
- if (name.isEmpty() && scope.isEmpty()) return;
- if (!type.isEmpty()) type+=" ";
- if (!scope.isEmpty()) type+=scope+"::";
- type+=name;
- scope.resize(0);
- name.resize(0);
-}
-
-static void addTypeName()
+struct declinfoYY_state
{
- //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n",
- // type.data(),scope.data(),name.data());
- if (name.isEmpty() ||
- name.at(name.length()-1)==':') // end of Objective-C keyword => append to name not type
- {
- return;
- }
- if (!type.isEmpty()) type+=' ';
- type+=name;
- name.resize(0);
-}
-
-#define YY_NEVER_INTERACTIVE 1
-
+ const char *inputString;
+ int inputPosition;
+ QCString scope;
+ QCString className;
+ QCString classTempList;
+ QCString funcTempList;
+ QCString type;
+ QCString name;
+ QCString args;
+ int sharpCount;
+ bool classTempListFound;
+ bool funcTempListFound;
+ QCString exceptionString;
+ bool insideObjC;
+};
+
+static void addType(yyscan_t yyscanner);
+static void addTypeName(yyscan_t yyscanner);
+static int yyread(char *buf,int max_size, yyscan_t yyscanner);
+
/* -----------------------------------------------------------------
*/
#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
-
-static int yyread(char *buf,int max_size)
-{
- int c=0;
- while( c < max_size && inputString[inputPosition] )
- {
- *buf = inputString[inputPosition++] ;
- c++; buf++;
- }
- return c;
-}
-
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
%}
B [ \t]
ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
-%option nounput
-%option noyywrap
-
%x Start
%x Template
%x ReadArgs
@@ -119,17 +87,17 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
%%
<Start>"operator"/({B}*"["{B}*"]")* { // operator rule must be before {ID} rule
- name += yytext;
+ yyextra->name += yytext;
BEGIN(Operator);
}
<Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories
- if (!insideObjC)
+ if (!yyextra->insideObjC)
{
REJECT;
}
else
{
- name += yytext;
+ yyextra->name += yytext;
}
}
<Start>([~!]{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java,
@@ -137,143 +105,195 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+)
// dimensional C++ arrays like A[][15]
// the leading ~ is for a destructor
// the leading ! is for a C++/CLI finalizer (see bug 456475 and 635198)
- addTypeName();
- name += yytext;
+ addTypeName(yyscanner);
+ yyextra->name += yytext;
}
-<Start>{B}*"::"{B}* { // found a scope specifier
- if (!scope.isEmpty())
+<Start>{B}*"::"{B}* { // found a yyextra->scope specifier
+ if (!yyextra->scope.isEmpty())
{
- scope+="::"+name; // add name to scope
+ yyextra->scope+="::"+yyextra->name; // add yyextra->name to yyextra->scope
}
else
{
- scope = name.copy(); // scope becomes name
+ yyextra->scope = yyextra->name.copy(); // yyextra->scope becomes yyextra->name
}
- name.resize(0);
+ yyextra->name.resize(0);
}
<Start>{B}*":" { // Objective-C argument separator
- name+=yytext;
+ yyextra->name+=yytext;
}
<Start>[*&]+ {
- addType();
- type+=yytext;
+ addType(yyscanner);
+ yyextra->type+=yytext;
}
<Start>{B}+ {
- addType();
+ addType(yyscanner);
}
<Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? {
- addType();
+ addType(yyscanner);
QCString text=yytext;
- type+=text.stripWhiteSpace();
+ yyextra->type+=text.stripWhiteSpace();
}
<Start>{B}*")" {
- type+=")";
+ yyextra->type+=")";
}
<Start>{B}*"(" { // TODO: function pointers
- args+="(";
+ yyextra->args+="(";
BEGIN(ReadArgs);
}
<Start>{B}*"[" {
- args+="[";
+ yyextra->args+="[";
BEGIN(ReadArgs);
}
<Start>{B}*"<" {
- name+="<";
- sharpCount=0;
+ yyextra->name+="<";
+ yyextra->sharpCount=0;
BEGIN(Template);
}
-<Template>"<<" { name+="<<"; }
-<Template>">>" { name+=">>"; }
+<Template>"<<" { yyextra->name+="<<"; }
+<Template>">>" { yyextra->name+=">>"; }
<Template>"<" {
- name+="<";
- sharpCount++;
+ yyextra->name+="<";
+ yyextra->sharpCount++;
}
<Template>">" {
- name+=">";
- if (sharpCount)
- --sharpCount;
+ yyextra->name+=">";
+ if (yyextra->sharpCount)
+ --yyextra->sharpCount;
else
{
BEGIN(Start);
}
}
<Template>. {
- name+=*yytext;
+ yyextra->name+=*yytext;
}
<Operator>{B}*"("{B}*")"{B}*"<>"{B}*/"(" {
- name+="() <>";
+ yyextra->name+="() <>";
BEGIN(ReadArgs);
}
<Operator>{B}*"("{B}*")"{B}*/"(" {
- name+="()";
+ yyextra->name+="()";
BEGIN(ReadArgs);
}
<Operator>[^(]*{B}*("<>"{B}*)?/"(" {
- name+=yytext;
+ yyextra->name+=yytext;
BEGIN(ReadArgs);
}
<ReadArgs>"throw"{B}*"(" {
- exceptionString="throw(";
+ yyextra->exceptionString="throw(";
BEGIN(ReadExceptions);
}
<ReadArgs>. {
- args+=*yytext;
+ yyextra->args+=*yytext;
}
<ReadExceptions>. {
- exceptionString+=*yytext;
+ yyextra->exceptionString+=*yytext;
}
<*>.
<*>\n
%%
-/*@ ----------------------------------------------------------------------------
+static void addType(yyscan_t yyscanner)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ //printf("addType() yyextra->type=`%s' yyextra->scope=`%s' yyextra->name=`%s'\n",
+ // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data());
+ if (yyextra->name.isEmpty() && yyextra->scope.isEmpty()) return;
+ if (!yyextra->type.isEmpty()) yyextra->type+=" ";
+ if (!yyextra->scope.isEmpty()) yyextra->type+=yyextra->scope+"::";
+ yyextra->type+=yyextra->name;
+ yyextra->scope.resize(0);
+ yyextra->name.resize(0);
+}
+
+static void addTypeName(yyscan_t yyscanner)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ //printf("addTypeName() yyextra->type=`%s' yyextra->scope=`%s' yyextra->name=`%s'\n",
+ // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data());
+ if (yyextra->name.isEmpty() ||
+ yyextra->name.at(yyextra->name.length()-1)==':') // end of Objective-C keyword => append to yyextra->name not yyextra->type
+ {
+ return;
+ }
+ if (!yyextra->type.isEmpty()) yyextra->type+=' ';
+ yyextra->type+=yyextra->name;
+ yyextra->name.resize(0);
+}
+
+static int yyread(char *buf,int max_size, yyscan_t yyscanner)
+{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ int c=0;
+ while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
+ {
+ *buf = yyextra->inputString[yyextra->inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+/*@ public interface------------------------------------------------------------
*/
+static yyscan_t g_yyscanner;
+static struct declinfoYY_state g_declinfo_extra;
void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t,
QCString &n,QCString &a,QCString &ftl,QCString &exc)
{
+ if (decl.isEmpty())
+ {
+ return;
+ }
+ declinfoYYlex_init_extra(&g_declinfo_extra, &g_yyscanner);
+ struct yyguts_t *yyg = (struct yyguts_t*)g_yyscanner;
+
+#ifdef FLEX_DEBUG
+ yyset_debug(1,g_yyscanner);
+#endif
+
printlex(yy_flex_debug, TRUE, __FILE__, NULL);
- inputString = decl;
- //printf("Input=`%s'\n",inputString);
- if (inputString==0) return;
- inputPosition = 0;
- classTempListFound = FALSE;
- funcTempListFound = FALSE;
- insideObjC = objC;
- scope.resize(0);
- className.resize(0);
- classTempList.resize(0);
- funcTempList.resize(0);
- name.resize(0);
- type.resize(0);
- args.resize(0);
- exceptionString.resize(0);
- // first we try to find the type, scope, name and arguments
- declinfoYYrestart( declinfoYYin );
+ yyextra->inputString = decl;
+ //printf("Input=`%s'\n",yyextra->inputString);
+ yyextra->inputPosition = 0;
+ yyextra->classTempListFound = FALSE;
+ yyextra->funcTempListFound = FALSE;
+ yyextra->insideObjC = objC;
+ yyextra->scope.resize(0);
+ yyextra->className.resize(0);
+ yyextra->classTempList.resize(0);
+ yyextra->funcTempList.resize(0);
+ yyextra->name.resize(0);
+ yyextra->type.resize(0);
+ yyextra->args.resize(0);
+ yyextra->exceptionString.resize(0);
+ // first we try to find the yyextra->type, yyextra->scope, yyextra->name and arguments
+ declinfoYYrestart( yyin, g_yyscanner );
BEGIN( Start );
- declinfoYYlex();
+ declinfoYYlex(g_yyscanner);
- //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
- // type.data(),scope.data(),name.data(),args.data());
+ //printf("yyextra->type=`%s' class=`%s' yyextra->name=`%s' yyextra->args=`%s'\n",
+ // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data(),yyextra->args.data());
- int nb = name.findRev('[');
- if (nb!=-1 && args.isEmpty()) // correct for [] in name ambigity (due to Java return type allowing [])
+ int nb = yyextra->name.findRev('[');
+ if (nb!=-1 && yyextra->args.isEmpty()) // correct for [] in yyextra->name ambigity (due to Java return yyextra->type allowing [])
{
- args.prepend(name.right(name.length()-nb));
- name=name.left(nb);
+ yyextra->args.prepend(yyextra->name.right(yyextra->name.length()-nb));
+ yyextra->name=yyextra->name.left(nb);
}
#if 0
{
- int l=scope.length();
+ int l=yyextra->scope.length();
int i=0;
int skipCount=0;
cl.resize(0);
ctl.resize(0);
for (i=0;i<l;i++)
{
- char c=scope.at(i);
+ char c=yyextra->scope.at(i);
if (c=='<')
skipCount++;
else if (c=='>')
@@ -282,12 +302,12 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t,
cl+=c;
}
}
- cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(scope),FALSE);
+ cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(yyextra->scope),FALSE);
ctl.resize(0);
#endif
- cl=scope;
- n=removeRedundantWhiteSpace(name);
+ cl=yyextra->scope;
+ n=removeRedundantWhiteSpace(yyextra->name);
int il,ir;
if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1)
// TODO: handle cases like where n="operator<< <T>"
@@ -296,24 +316,23 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t,
n=n.left(il);
}
- //ctl=classTempList.copy();
- //ftl=funcTempList.copy();
- t=removeRedundantWhiteSpace(type);
- a=removeRedundantWhiteSpace(args);
- exc=removeRedundantWhiteSpace(exceptionString);
+ //ctl=yyextra->classTempList.copy();
+ //ftl=yyextra->funcTempList.copy();
+ t=removeRedundantWhiteSpace(yyextra->type);
+ a=removeRedundantWhiteSpace(yyextra->args);
+ exc=removeRedundantWhiteSpace(yyextra->exceptionString);
if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers
{
a.prepend(")");
t=t.left(t.length()-1);
}
- //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
+ //printf("yyextra->type=`%s' class=`%s' yyextra->name=`%s' yyextra->args=`%s'\n",
// t.data(),cl.data(),n.data(),a.data());
printlex(yy_flex_debug, FALSE, __FILE__, NULL);
+ declinfoYYlex_destroy(g_yyscanner);
return;
-
-
}
//extern "C" { // some bogus code to keep the compiler happy
@@ -324,18 +343,18 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t,
#if 0
void dumpDecl(const char *s)
{
- QCString className;
+ QCString yyextra->className;
QCString classTNames;
- QCString type;
- QCString name;
- QCString args;
+ QCString yyextra->type;
+ QCString yyextra->name;
+ QCString yyextra->args;
QCString funcTNames;
msg("-----------------------------------------\n");
- parseFuncDecl(s,className,classTNames,type,name,args,funcTNames);
- msg("type=`%s' class=`%s' classTempl=`%s' name=`%s' "
- "funcTemplateNames=`%s' args=`%s'\n",
- type.data(),className.data(),classTNames.data(),
- name.data(),funcTNames.data(),args.data()
+ parseFuncDecl(s,yyextra->className,classTNames,yyextra->type,yyextra->name,yyextra->args,funcTNames);
+ msg("yyextra->type=`%s' class=`%s' classTempl=`%s' yyextra->name=`%s' "
+ "funcTemplateNames=`%s' yyextra->args=`%s'\n",
+ yyextra->type.data(),yyextra->className.data(),classTNames.data(),
+ yyextra->name.data(),funcTNames.data(),yyextra->args.data()
);
}
@@ -346,11 +365,11 @@ int main()
dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
dumpDecl("func()");
dumpDecl("friend void bla<>()");
- dumpDecl("name< T > :: operator () (int bla)");
- dumpDecl("name< T > :: operator << (int bla)");
- dumpDecl("name< T > :: operator << <> (int bla)");
- dumpDecl("className::func()");
- dumpDecl("void ( * Name < T > :: bla ) ( int, char * )");
+ dumpDecl("yyextra->name< T > :: operator () (int bla)");
+ dumpDecl("yyextra->name< T > :: operator << (int bla)");
+ dumpDecl("yyextra->name< T > :: operator << <> (int bla)");
+ dumpDecl("yyextra->className::func()");
+ dumpDecl("void ( * yyextra->Name < T > :: bla ) ( int, char * )");
}
#endif
diff --git a/src/defgen.cpp b/src/defgen.cpp
index a8f89c5..ab19c2a 100644
--- a/src/defgen.cpp
+++ b/src/defgen.cpp
@@ -27,6 +27,7 @@
#include "defargs.h"
#include "outputgen.h"
#include "dot.h"
+#include "dotclassgraph.h"
#include "arguments.h"
#include "memberlist.h"
#include "namespacedef.h"
@@ -144,7 +145,7 @@ void generateDEFForMember(MemberDef *md,
if (isFunc) //function
{
ArgumentList *declAl = new ArgumentList;
- ArgumentList *defAl = md->argumentList();
+ const ArgumentList *defAl = md->argumentList();
stringToArgumentList(md->argsString(),declAl);
QCString fcnPrefix = " " + memPrefix + "param-";
@@ -220,7 +221,7 @@ void generateDEFForMember(MemberDef *md,
// TODO: exceptions, const volatile
if (md->memberType()==MemberType_Enumeration) // enum
{
- MemberList *enumList = md->enumFieldList();
+ const MemberList *enumList = md->enumFieldList();
if (enumList!=0)
{
MemberListIterator emli(*enumList);
@@ -466,14 +467,14 @@ void generateDEFForClass(ClassDef *cd,FTextStream &t)
t << " cp-documentation = <<_EnD_oF_dEf_TeXt_" << endl
<< cd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
- DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
+ DotClassGraph inheritanceGraph(cd,Inheritance);
if (!inheritanceGraph.isTrivial())
{
t << " cp-inheritancegraph = <<_EnD_oF_dEf_TeXt_" << endl;
inheritanceGraph.writeDEF(t);
t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
}
- DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
+ DotClassGraph collaborationGraph(cd,Collaboration);
if (!collaborationGraph.isTrivial())
{
t << " cp-collaborationgraph = <<_EnD_oF_dEf_TeXt_" << endl;
diff --git a/src/definition.cpp b/src/definition.cpp
index 1233add..b9c40f6 100644
--- a/src/definition.cpp
+++ b/src/definition.cpp
@@ -223,7 +223,7 @@ static bool matchExcludedSymbols(const char *name)
return FALSE;
}
-void DefinitionImpl::addToMap(const char *name,Definition *d)
+static void addToMap(const char *name,Definition *d)
{
bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
QCString symbolName = name;
@@ -270,7 +270,7 @@ void DefinitionImpl::addToMap(const char *name,Definition *d)
}
}
-void DefinitionImpl::removeFromMap(Definition *d)
+static void removeFromMap(Definition *d)
{
QCString symbolName = d->_symbolName();
if (!symbolName.isEmpty())
@@ -532,7 +532,7 @@ void DefinitionImpl::addSectionsToIndex()
}
}
-void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile)
+void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) const
{
if (m_impl->sectionDict)
{
@@ -1047,7 +1047,7 @@ QCString DefinitionImpl::getSourceAnchor() const
}
/*! Write a reference to the source code defining this definition */
-void DefinitionImpl::writeSourceDef(OutputList &ol,const char *)
+void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const
{
static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE);
@@ -1259,7 +1259,7 @@ bool DefinitionImpl::hasSources() const
}
/*! Write code of this definition into the documentation */
-void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName)
+void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const
{
static bool inlineSources = Config_getBool(INLINE_SOURCES);
ol.pushGeneratorState();
@@ -1278,8 +1278,8 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName)
ParserInterface *pIntf = Doxygen::parserManager->getParser(m_impl->defFileExt);
pIntf->resetCodeParserState();
//printf("Read:\n`%s'\n\n",codeFragment.data());
- MemberDef *thisMd = 0;
- if (definitionType()==TypeMember) thisMd = dynamic_cast <MemberDef*>(this);
+ const MemberDef *thisMd = 0;
+ if (definitionType()==TypeMember) thisMd = dynamic_cast <const MemberDef*>(this);
ol.startCodeFragment();
pIntf->parseCode(ol, // codeOutIntf
@@ -1305,7 +1305,7 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName)
* definition is used.
*/
void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName,
- const QCString &text,MemberSDict *members,bool /*funcOnly*/)
+ const QCString &text,MemberSDict *members,bool /*funcOnly*/) const
{
static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING);
@@ -1456,12 +1456,12 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName,
ol.popGeneratorState();
}
-void DefinitionImpl::writeSourceReffedBy(OutputList &ol,const char *scopeName)
+void DefinitionImpl::writeSourceReffedBy(OutputList &ol,const char *scopeName) const
{
_writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE);
}
-void DefinitionImpl::writeSourceRefs(OutputList &ol,const char *scopeName)
+void DefinitionImpl::writeSourceRefs(OutputList &ol,const char *scopeName) const
{
_writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE);
}
@@ -1491,7 +1491,7 @@ bool DefinitionImpl::hasUserDocumentation() const
}
-void DefinitionImpl::addSourceReferencedBy(MemberDef *md)
+void DefinitionImpl::addSourceReferencedBy(const MemberDef *md)
{
if (md)
{
@@ -1514,7 +1514,7 @@ void DefinitionImpl::addSourceReferencedBy(MemberDef *md)
}
}
-void DefinitionImpl::addSourceReferences(MemberDef *md)
+void DefinitionImpl::addSourceReferences(const MemberDef *md)
{
if (md)
{
@@ -1542,7 +1542,7 @@ Definition *DefinitionImpl::findInnerCompound(const char *) const
return 0;
}
-void DefinitionImpl::addInnerCompound(Definition *)
+void DefinitionImpl::addInnerCompound(const Definition *)
{
err("DefinitionImpl::addInnerCompound() called\n");
}
@@ -1796,7 +1796,7 @@ void DefinitionImpl::writeNavigationPath(OutputList &ol) const
}
// TODO: move to htmlgen
-void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc)
+void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const
{
SectionDict *sectionDict = m_impl->sectionDict;
if (sectionDict==0) return;
@@ -1936,7 +1936,7 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc)
//----------------------------------------------------------------------------------------
-SectionDict * DefinitionImpl::getSectionDict(void)
+SectionDict * DefinitionImpl::getSectionDict() const
{
return m_impl->sectionDict;
}
@@ -2251,7 +2251,7 @@ int DefinitionImpl::getDefColumn() const
return m_impl->defColumn;
}
-void DefinitionImpl::setCookie(Cookie *cookie)
+void DefinitionImpl::setCookie(Cookie *cookie) const
{
delete m_impl->cookie;
m_impl->cookie = cookie;
@@ -2262,11 +2262,26 @@ Definition::Cookie *DefinitionImpl::cookie() const
return m_impl->cookie;
}
-void DefinitionImpl::writeQuickMemberLinks(OutputList &,MemberDef *) const
+void DefinitionImpl::writeQuickMemberLinks(OutputList &,const MemberDef *) const
{
}
-void DefinitionImpl::writeSummaryLinks(OutputList &)
+void DefinitionImpl::writeSummaryLinks(OutputList &) const
{
}
+//---------------------------------------------------------------------------------
+
+DefinitionAliasImpl::DefinitionAliasImpl(const Definition *scope,const Definition *alias)
+ : m_scope(scope), m_def(alias), m_cookie(0)
+{
+ //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name()));
+ addToMap(alias->name(),this);
+}
+
+DefinitionAliasImpl::~DefinitionAliasImpl()
+{
+ //printf("~DefinitionAliasImpl()\n");
+ removeFromMap(this);
+}
+
diff --git a/src/definition.h b/src/definition.h
index a2307f7..db9bbbc 100644
--- a/src/definition.h
+++ b/src/definition.h
@@ -105,6 +105,8 @@ class Definition : public DefinitionIntf
//-----------------------------------------------------------------------------------
// ---- getters -----
//-----------------------------------------------------------------------------------
+ /*! Returns TRUE if this is an alias of another definition */
+ virtual bool isAlias() const = 0;
/*! Returns the name of the definition */
virtual QCString name() const = 0;
@@ -272,7 +274,10 @@ class Definition : public DefinitionIntf
virtual QCString id() const = 0;
/** returns the section dictionary, only of importance for pagedef */
- virtual SectionDict * getSectionDict(void) = 0;
+ virtual SectionDict * getSectionDict() const = 0;
+
+ virtual QCString navigationPathAsString() const = 0;
+ virtual QCString pathFragment() const = 0;
//-----------------------------------------------------------------------------------
// ---- setters -----
@@ -304,54 +309,57 @@ class Definition : public DefinitionIntf
/*! Sets the tag file id via which this definition was imported. */
virtual void setReference(const char *r) = 0;
- /*! Add the list of anchors that mark the sections that are found in the
- * documentation.
- */
- virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) = 0;
-
// source references
virtual void setBodySegment(int bls,int ble) = 0;
virtual void setBodyDef(FileDef *fd) = 0;
- virtual void addSourceReferencedBy(MemberDef *d) = 0;
- virtual void addSourceReferences(MemberDef *d) = 0;
virtual void setRefItems(const QList<ListItemInfo> *sli) = 0;
- virtual void mergeRefItems(Definition *d) = 0;
- virtual void addInnerCompound(Definition *d) = 0;
virtual void setOuterScope(Definition *d) = 0;
virtual void setHidden(bool b) = 0;
virtual void setArtificial(bool b) = 0;
virtual void setLanguage(SrcLangExt lang) = 0;
+ virtual void setLocalName(const QCString name) = 0;
//-----------------------------------------------------------------------------------
// --- actions ----
//-----------------------------------------------------------------------------------
- virtual void writeSourceDef(OutputList &ol,const char *scopeName) = 0;
- virtual void writeInlineCode(OutputList &ol,const char *scopeName) = 0;
- virtual void writeSourceRefs(OutputList &ol,const char *scopeName) = 0;
- virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) = 0;
virtual void makePartOfGroup(GroupDef *gd) = 0;
- virtual void writeNavigationPath(OutputList &ol) const = 0;
- virtual QCString navigationPathAsString() const = 0;
- virtual void writeQuickMemberLinks(OutputList &,MemberDef *) const = 0;
- virtual void writeSummaryLinks(OutputList &) = 0;
- virtual QCString pathFragment() const = 0;
- /*! Writes the documentation anchors of the definition to
- * the Doxygen::tagFile stream.
+ /*! Add the list of anchors that mark the sections that are found in the
+ * documentation.
*/
- virtual void writeDocAnchorsToTagFile(FTextStream &) = 0;
- virtual void setLocalName(const QCString name) = 0;
-
+ virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) = 0;
+ virtual void addSourceReferencedBy(const MemberDef *d) = 0;
+ virtual void addSourceReferences(const MemberDef *d) = 0;
+ virtual void mergeRefItems(Definition *d) = 0;
+ virtual void addInnerCompound(const Definition *d) = 0;
virtual void addSectionsToIndex() = 0;
- virtual void writeToc(OutputList &ol, const LocalToc &lt) = 0;
- virtual void setCookie(Cookie *cookie) = 0;
+ //-----------------------------------------------------------------------------------
+ // --- writing output ----
+ //-----------------------------------------------------------------------------------
+ virtual void writeSourceDef(OutputList &ol,const char *scopeName) const = 0;
+ virtual void writeInlineCode(OutputList &ol,const char *scopeName) const = 0;
+ virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const = 0;
+ virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const = 0;
+ virtual void writeNavigationPath(OutputList &ol) const = 0;
+ virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const = 0;
+ virtual void writeSummaryLinks(OutputList &) const = 0;
+ virtual void writeDocAnchorsToTagFile(FTextStream &) const = 0;
+ virtual void writeToc(OutputList &ol, const LocalToc &lt) const = 0;
+
+ //-----------------------------------------------------------------------------------
+ // --- cookie storage ----
+ //-----------------------------------------------------------------------------------
+ virtual void setCookie(Cookie *cookie) const = 0;
virtual Cookie *cookie() const = 0;
+ //-----------------------------------------------------------------------------------
+ // --- symbol name ----
+ //-----------------------------------------------------------------------------------
virtual void _setSymbolName(const QCString &name) = 0;
virtual QCString _symbolName() const = 0;
};
diff --git a/src/definitionimpl.h b/src/definitionimpl.h
index 864d35b..4dd324b 100644
--- a/src/definitionimpl.h
+++ b/src/definitionimpl.h
@@ -30,13 +30,11 @@ class DefinitionImpl : virtual public Definition
bool isSymbol=TRUE);
virtual ~DefinitionImpl();
+ virtual bool isAlias() const { return FALSE; }
virtual QCString name() const;
- virtual QCString displayName(bool includeScope=TRUE) const = 0;
virtual QCString localName() const;
virtual QCString qualifiedName() const;
virtual QCString symbolName() const;
- virtual QCString getOutputFileBase() const = 0;
- virtual QCString anchor() const = 0;
virtual QCString getSourceFileBase() const;
virtual QCString getSourceAnchor() const;
virtual QCString documentation() const;
@@ -55,8 +53,6 @@ class DefinitionImpl : virtual public Definition
virtual int getDefColumn() const;
virtual bool hasDocumentation() const;
virtual bool hasUserDocumentation() const;
- virtual bool isLinkableInProject() const = 0;
- virtual bool isLinkable() const = 0;
virtual bool isVisibleInProject() const;
virtual bool isVisible() const;
virtual bool isHidden() const;
@@ -79,7 +75,7 @@ class DefinitionImpl : virtual public Definition
virtual bool hasSources() const;
virtual bool hasBriefDescription() const;
virtual QCString id() const;
- virtual SectionDict * getSectionDict(void);
+ virtual SectionDict * getSectionDict() const;
virtual void setName(const char *name);
virtual void setId(const char *name);
virtual void setDefFile(const QCString& df,int defLine,int defColumn);
@@ -90,30 +86,30 @@ class DefinitionImpl : virtual public Definition
virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList);
virtual void setBodySegment(int bls,int ble);
virtual void setBodyDef(FileDef *fd);
- virtual void addSourceReferencedBy(MemberDef *d);
- virtual void addSourceReferences(MemberDef *d);
+ virtual void addSourceReferencedBy(const MemberDef *d);
+ virtual void addSourceReferences(const MemberDef *d);
virtual void setRefItems(const QList<ListItemInfo> *sli);
virtual void mergeRefItems(Definition *d);
- virtual void addInnerCompound(Definition *d);
+ virtual void addInnerCompound(const Definition *d);
virtual void setOuterScope(Definition *d);
virtual void setHidden(bool b);
virtual void setArtificial(bool b);
virtual void setLanguage(SrcLangExt lang);
- virtual void writeSourceDef(OutputList &ol,const char *scopeName);
- virtual void writeInlineCode(OutputList &ol,const char *scopeName);
- virtual void writeSourceRefs(OutputList &ol,const char *scopeName);
- virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName);
+ virtual void writeSourceDef(OutputList &ol,const char *scopeName) const;
+ virtual void writeInlineCode(OutputList &ol,const char *scopeName) const;
+ virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const;
+ virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const;
virtual void makePartOfGroup(GroupDef *gd);
virtual void writeNavigationPath(OutputList &ol) const;
virtual QCString navigationPathAsString() const;
- virtual void writeQuickMemberLinks(OutputList &,MemberDef *) const;
- virtual void writeSummaryLinks(OutputList &);
+ virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const;
+ virtual void writeSummaryLinks(OutputList &) const;
virtual QCString pathFragment() const;
- virtual void writeDocAnchorsToTagFile(FTextStream &);
+ virtual void writeDocAnchorsToTagFile(FTextStream &) const;
virtual void setLocalName(const QCString name);
virtual void addSectionsToIndex();
- virtual void writeToc(OutputList &ol, const LocalToc &lt);
- virtual void setCookie(Cookie *cookie);
+ virtual void writeToc(OutputList &ol, const LocalToc &lt) const;
+ virtual void setCookie(Cookie *cookie) const;
virtual Cookie *cookie() const;
protected:
@@ -121,15 +117,12 @@ class DefinitionImpl : virtual public Definition
DefinitionImpl(const DefinitionImpl &d);
private:
- static void addToMap(const char *name,Definition *d);
- static void removeFromMap(Definition *d);
-
virtual void _setSymbolName(const QCString &name);
virtual QCString _symbolName() const ;
int _getXRefListId(const char *listName) const;
void _writeSourceRefList(OutputList &ol,const char *scopeName,
- const QCString &text,MemberSDict *members,bool);
+ const QCString &text,MemberSDict *members,bool) const;
void _setBriefDescription(const char *b,const char *briefFile,int briefLine);
void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace,bool atTop);
void _setInbodyDocumentation(const char *d,const char *docFile,int docLine);
@@ -140,5 +133,152 @@ class DefinitionImpl : virtual public Definition
IMPL *m_impl; // internal structure holding all private data
};
+class DefinitionAliasImpl : virtual public Definition
+{
+ public:
+ DefinitionAliasImpl(const Definition *scope,const Definition *alias);
+ virtual ~DefinitionAliasImpl();
+
+ virtual bool isAlias() const { return TRUE; }
+ virtual QCString name() const
+ { return m_def->name(); }
+ virtual QCString localName() const
+ { return m_def->localName(); }
+ virtual QCString qualifiedName() const
+ { return m_def->qualifiedName(); }
+ virtual QCString symbolName() const
+ { return m_def->symbolName(); }
+ virtual QCString getSourceFileBase() const
+ { return m_def->getSourceFileBase(); }
+ virtual QCString getSourceAnchor() const
+ { return m_def->getSourceAnchor(); }
+ virtual QCString documentation() const
+ { return m_def->documentation(); }
+ virtual int docLine() const
+ { return m_def->docLine(); }
+ virtual QCString docFile() const
+ { return m_def->docFile(); }
+ virtual QCString briefDescription(bool abbreviate=FALSE) const
+ { return m_def->briefDescription(abbreviate); }
+ virtual QCString briefDescriptionAsTooltip() const
+ { return m_def->briefDescriptionAsTooltip(); }
+ virtual int briefLine() const
+ { return m_def->briefLine(); }
+ virtual QCString inbodyDocumentation() const
+ { return m_def->inbodyDocumentation(); }
+ virtual QCString inbodyFile() const
+ { return m_def->inbodyFile(); }
+ virtual int inbodyLine() const
+ { return m_def->inbodyLine(); }
+ virtual QCString briefFile() const
+ { return m_def->briefFile(); }
+ virtual QCString getDefFileName() const
+ { return m_def->getDefFileName(); }
+ virtual QCString getDefFileExtension() const
+ { return m_def->getDefFileExtension(); }
+ virtual int getDefLine() const
+ { return m_def->getDefLine(); }
+ virtual int getDefColumn() const
+ { return m_def->getDefColumn(); }
+ virtual bool hasDocumentation() const
+ { return m_def->hasDocumentation(); }
+ virtual bool hasUserDocumentation() const
+ { return m_def->hasUserDocumentation(); }
+ virtual bool isVisibleInProject() const
+ { return m_def->isVisibleInProject(); }
+ virtual bool isVisible() const
+ { return m_def->isVisible(); }
+ virtual bool isHidden() const
+ { return m_def->isHidden(); }
+ virtual bool isArtificial() const
+ { return m_def->isArtificial(); }
+ virtual QCString getReference() const
+ { return m_def->getReference(); }
+ virtual bool isReference() const
+ { return m_def->isReference(); }
+ virtual QCString externalReference(const QCString &relPath) const
+ { return m_def->externalReference(relPath); }
+ virtual int getStartBodyLine() const
+ { return m_def->getStartBodyLine(); }
+ virtual int getEndBodyLine() const
+ { return m_def->getEndBodyLine(); }
+ virtual FileDef *getBodyDef() const
+ { return m_def->getBodyDef(); }
+ virtual SrcLangExt getLanguage() const
+ { return m_def->getLanguage(); }
+ virtual GroupList *partOfGroups() const
+ { return m_def->partOfGroups(); }
+ virtual bool isLinkableViaGroup() const
+ { return m_def->isLinkableViaGroup(); }
+ virtual QList<ListItemInfo> *xrefListItems() const
+ { return m_def->xrefListItems(); }
+ virtual Definition *findInnerCompound(const char *name) const
+ { return m_def->findInnerCompound(name); }
+ virtual Definition *getOuterScope() const
+ { return const_cast<Definition*>(m_scope); }
+ virtual MemberSDict *getReferencesMembers() const
+ { return m_def->getReferencesMembers(); }
+ virtual MemberSDict *getReferencedByMembers() const
+ { return m_def->getReferencedByMembers(); }
+ virtual bool hasSections() const
+ { return m_def->hasSections(); }
+ virtual bool hasSources() const
+ { return m_def->hasSources(); }
+ virtual bool hasBriefDescription() const
+ { return m_def->hasBriefDescription(); }
+ virtual QCString id() const
+ { return m_def->id(); }
+ virtual SectionDict * getSectionDict() const
+ { return m_def->getSectionDict(); }
+ virtual QCString navigationPathAsString() const
+ { return m_def->navigationPathAsString(); }
+ virtual QCString pathFragment() const
+ { return m_def->pathFragment(); }
+ virtual void setName(const char *name) { }
+ virtual void setId(const char *name) { }
+ virtual void setDefFile(const QCString& df,int defLine,int defColumn) {}
+ virtual void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) {}
+ virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine) {}
+ virtual void setInbodyDocumentation(const char *d,const char *docFile,int docLine) {}
+ virtual void setReference(const char *r) {}
+ virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) {}
+ virtual void setBodySegment(int bls,int ble) {}
+ virtual void setBodyDef(FileDef *fd) {}
+ virtual void addSourceReferencedBy(const MemberDef *d) {}
+ virtual void addSourceReferences(const MemberDef *d) {}
+ virtual void setRefItems(const QList<ListItemInfo> *sli) {}
+ virtual void mergeRefItems(Definition *d) {}
+ virtual void addInnerCompound(const Definition *d) {}
+ virtual void setOuterScope(Definition *d) {}
+ virtual void setHidden(bool b) {}
+ virtual void setArtificial(bool b) {}
+ virtual void setLanguage(SrcLangExt lang) {}
+ virtual void writeSourceDef(OutputList &ol,const char *scopeName) const {}
+ virtual void writeInlineCode(OutputList &ol,const char *scopeName) const {}
+ virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const {}
+ virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const {}
+ virtual void makePartOfGroup(GroupDef *gd) {}
+ virtual void writeNavigationPath(OutputList &ol) const {}
+ virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {}
+ virtual void writeSummaryLinks(OutputList &) const {}
+ virtual void writeDocAnchorsToTagFile(FTextStream &) const {}
+ virtual void setLocalName(const QCString name) {}
+ virtual void addSectionsToIndex() {}
+ virtual void writeToc(OutputList &ol, const LocalToc &lt) const {}
+ virtual void setCookie(Cookie *cookie) const { delete m_cookie; m_cookie = cookie; }
+ virtual Cookie *cookie() const { return m_cookie; }
+ protected:
+ const Definition *getAlias() const { return m_def; }
+ const Definition *getScope() const { return m_scope; }
+
+ private:
+ virtual void _setSymbolName(const QCString &name) { m_symbolName = name; }
+ virtual QCString _symbolName() const { return m_symbolName; }
+ const Definition *m_scope;
+ const Definition *m_def;
+ mutable Cookie *m_cookie;
+ QCString m_symbolName;
+};
+
#endif
diff --git a/src/dia.cpp b/src/dia.cpp
index 5adbc7c..8dab5b0 100644
--- a/src/dia.cpp
+++ b/src/dia.cpp
@@ -65,6 +65,8 @@ void writeDiaGraphFromFile(const char *inFile,const char *outDir,
portable_sysTimerStart();
if ((exitCode=portable_system(diaExe,diaArgs,FALSE))!=0)
{
+ err("Problems running %s. Check your installation or look typos in you dia file %s\n",
+ diaExe.data(),inFile);
portable_sysTimerStop();
goto error;
}
diff --git a/src/diagram.cpp b/src/diagram.cpp
index 808191e..06480fc 100644
--- a/src/diagram.cpp
+++ b/src/diagram.cpp
@@ -42,7 +42,7 @@ class DiagramItemList;
class DiagramItem
{
public:
- DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+ DiagramItem(DiagramItem *p,int number,const ClassDef *cd,
Protection prot,Specifier virt,const char *ts);
~DiagramItem();
QCString label() const;
@@ -60,7 +60,7 @@ class DiagramItem
Specifier virtualness() const { return virt; }
void putInList() { inList=TRUE; }
bool isInList() const { return inList; }
- ClassDef *getClassDef() const { return classDef; }
+ const ClassDef *getClassDef() const { return classDef; }
private:
DiagramItemList *children;
DiagramItem *parent;
@@ -70,7 +70,7 @@ class DiagramItem
Specifier virt;
QCString templSpec;
bool inList;
- ClassDef *classDef;
+ const ClassDef *classDef;
};
/** Class representing a list of DiagramItem object. */
@@ -91,7 +91,7 @@ class DiagramRow : public QList<DiagramItem>
level=l;
setAutoDelete(TRUE);
}
- void insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+ void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases,
Protection prot,Specifier virt,const char *ts);
uint number() { return level; }
private:
@@ -111,7 +111,7 @@ class DiagramRowIterator : public QListIterator<DiagramRow>
class TreeDiagram : public QList<DiagramRow>
{
public:
- TreeDiagram(ClassDef *root,bool doBases);
+ TreeDiagram(const ClassDef *root,bool doBases);
~TreeDiagram();
void computeLayout();
uint computeRows();
@@ -252,7 +252,7 @@ static void writeVectorBox(FTextStream &t,DiagramItem *di,
if (di->virtualness()==Virtual) t << "solid\n";
}
-static void writeMapArea(FTextStream &t,ClassDef *cd,QCString relPath,
+static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath,
int x,int y,int w,int h)
{
if (cd->isLinkable())
@@ -283,7 +283,7 @@ static void writeMapArea(FTextStream &t,ClassDef *cd,QCString relPath,
}
//-----------------------------------------------------------------------------
-DiagramItem::DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+DiagramItem::DiagramItem(DiagramItem *p,int number,const ClassDef *cd,
Protection pr,Specifier vi,const char *ts)
{
parent=p;
@@ -354,7 +354,7 @@ void DiagramItem::addChild(DiagramItem *di)
children->append(di);
}
-void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases,
Protection prot,Specifier virt,const char *ts)
{
//if (cd->visited) return; // the visit check does not work in case of
@@ -406,7 +406,7 @@ void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
}
}
-TreeDiagram::TreeDiagram(ClassDef *root,bool doBases)
+TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases)
{
setAutoDelete(TRUE);
DiagramRow *row=new DiagramRow(this,0);
@@ -1024,7 +1024,7 @@ void clearVisitFlags()
}
}
-ClassDiagram::ClassDiagram(ClassDef *root)
+ClassDiagram::ClassDiagram(const ClassDef *root)
{
clearVisitFlags();
base = new TreeDiagram(root,TRUE);
diff --git a/src/diagram.h b/src/diagram.h
index 2922657..05af28e 100644
--- a/src/diagram.h
+++ b/src/diagram.h
@@ -29,7 +29,7 @@ class FTextStream;
class ClassDiagram
{
public:
- ClassDiagram(ClassDef *root);
+ ClassDiagram(const ClassDef *root);
~ClassDiagram();
void writeFigure(FTextStream &t,const char *path,
const char *file) const;
diff --git a/src/dirdef.cpp b/src/dirdef.cpp
index ae3a6a3..5db8b99 100644
--- a/src/dirdef.cpp
+++ b/src/dirdef.cpp
@@ -8,6 +8,7 @@
#include "language.h"
#include "message.h"
#include "dot.h"
+#include "dotdirdeps.h"
#include "layout.h"
#include "ftextstream.h"
#include "config.h"
@@ -38,7 +39,7 @@ class DirDefImpl : public DefinitionImpl, public DirDef
virtual DirDef *parent() const { return m_parent; }
virtual int dirCount() const { return m_dirCount; }
virtual const QDict<UsedDir> *usedDirs() const { return m_usedDirs; }
- virtual bool isParentOf(DirDef *dir) const;
+ virtual bool isParentOf(const DirDef *dir) const;
virtual bool depGraphIsTrivial() const;
virtual QCString shortTitle() const;
virtual bool hasDetailedDescription() const;
@@ -726,7 +727,7 @@ void DirDefImpl::computeDependencies()
}
}
-bool DirDefImpl::isParentOf(DirDef *dir) const
+bool DirDefImpl::isParentOf(const DirDef *dir) const
{
if (dir->parent()==this) // this is a parent of dir
return TRUE;
diff --git a/src/dirdef.h b/src/dirdef.h
index 2bca93e..2ea54af 100644
--- a/src/dirdef.h
+++ b/src/dirdef.h
@@ -63,7 +63,7 @@ class DirDef : virtual public Definition
virtual DirDef *parent() const = 0;
virtual int dirCount() const = 0;
virtual const QDict<UsedDir> *usedDirs() const = 0;
- virtual bool isParentOf(DirDef *dir) const = 0;
+ virtual bool isParentOf(const DirDef *dir) const = 0;
virtual bool depGraphIsTrivial() const = 0;
virtual QCString shortTitle() const = 0;
virtual bool hasDetailedDescription() const = 0;
@@ -125,16 +125,16 @@ class UsedDir
class DirRelation
{
public:
- DirRelation(const QCString &name,DirDef *src,UsedDir *dst)
+ DirRelation(const QCString &name,const DirDef *src,UsedDir *dst)
: m_name(name), m_src(src), m_dst(dst) {}
- DirDef *source() const { return m_src; }
+ const DirDef *source() const { return m_src; }
UsedDir *destination() const { return m_dst; }
void writeDocumentation(OutputList &ol);
QCString getOutputFileBase() const { return m_name; }
private:
QCString m_name;
- DirDef *m_src;
+ const DirDef *m_src;
UsedDir *m_dst;
};
diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp
index adf36b0..7fe849a 100644
--- a/src/docbookgen.cpp
+++ b/src/docbookgen.cpp
@@ -33,6 +33,11 @@
#include "defargs.h"
#include "outputgen.h"
#include "dot.h"
+#include "dotcallgraph.h"
+#include "dotclassgraph.h"
+#include "dotdirdeps.h"
+#include "dotgroupcollaboration.h"
+#include "dotincldepgraph.h"
#include "pagedef.h"
#include "filename.h"
#include "version.h"
@@ -180,7 +185,7 @@ void DocbookCodeGenerator::startCodeLine(bool)
}
void DocbookCodeGenerator::endCodeLine()
{
- m_t << endl;
+ if (m_insideCodeLine) m_t << endl;
Docbook_DB(("(endCodeLine)\n"));
m_lineNumber = -1;
m_refId.resize(0);
@@ -230,7 +235,7 @@ void DocbookCodeGenerator::writeLineNumber(const char *ref,const char *fileName,
}
}
-void DocbookCodeGenerator::setCurrentDoc(Definition *,const char *,bool)
+void DocbookCodeGenerator::setCurrentDoc(const Definition *,const char *,bool)
{
}
void DocbookCodeGenerator::addWord(const char *,bool)
@@ -238,7 +243,7 @@ void DocbookCodeGenerator::addWord(const char *,bool)
}
void DocbookCodeGenerator::finish()
{
- if (m_insideCodeLine) endCodeLine();
+ endCodeLine();
}
void DocbookCodeGenerator::startCodeFragment()
{
@@ -246,6 +251,9 @@ void DocbookCodeGenerator::startCodeFragment()
}
void DocbookCodeGenerator::endCodeFragment()
{
+ //endCodeLine checks is there is still an open code line, if so closes it.
+ endCodeLine();
+
m_t << "</computeroutput></literallayout>" << endl;
}
@@ -537,7 +545,7 @@ DB_GEN_C2("IndexSections " << is)
{
t << "</title>" << endl;
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd=0;
+ const ClassDef *cd=0;
bool found=FALSE;
for (cli.toFirst();(cd=cli.current()) && !found;++cli)
{
@@ -572,7 +580,7 @@ DB_GEN_C2("IndexSections " << is)
for (fnli.toFirst();(fn=fnli.current());++fnli)
{
FileNameIterator fni(*fn);
- FileDef *fd;
+ const FileDef *fd;
for (;(fd=fni.current());++fni)
{
if (fd->isLinkableInProject())
@@ -648,7 +656,7 @@ DB_GEN_C
}
}
}
-void DocbookGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
+void DocbookGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *)
{
DB_GEN_C
DocbookDocVisitor *visitor =
@@ -1002,6 +1010,9 @@ DB_GEN_C
void DocbookGenerator::endCodeFragment()
{
DB_GEN_C
+ //endCodeLine checks is there is still an open code line, if so closes it.
+ endCodeLine();
+
t << "</programlisting>";
}
void DocbookGenerator::startMemberTemplateParams()
@@ -1095,7 +1106,7 @@ void DocbookGenerator::startGroupCollaboration()
{
DB_GEN_C
}
-void DocbookGenerator::endGroupCollaboration(const DotGroupCollaboration &g)
+void DocbookGenerator::endGroupCollaboration(DotGroupCollaboration &g)
{
DB_GEN_C
g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE);
@@ -1104,7 +1115,7 @@ void DocbookGenerator::startDotGraph()
{
DB_GEN_C
}
-void DocbookGenerator::endDotGraph(const DotClassGraph &g)
+void DocbookGenerator::endDotGraph(DotClassGraph &g)
{
DB_GEN_C
g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE);
@@ -1113,7 +1124,7 @@ void DocbookGenerator::startInclDepGraph()
{
DB_GEN_C
}
-void DocbookGenerator::endInclDepGraph(const DotInclDepGraph &g)
+void DocbookGenerator::endInclDepGraph(DotInclDepGraph &g)
{
DB_GEN_C
QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE);
@@ -1122,7 +1133,7 @@ void DocbookGenerator::startCallGraph()
{
DB_GEN_C
}
-void DocbookGenerator::endCallGraph(const DotCallGraph &g)
+void DocbookGenerator::endCallGraph(DotCallGraph &g)
{
DB_GEN_C
QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE);
@@ -1131,7 +1142,7 @@ void DocbookGenerator::startDirDepGraph()
{
DB_GEN_C
}
-void DocbookGenerator::endDirDepGraph(const DotDirDeps &g)
+void DocbookGenerator::endDirDepGraph(DotDirDeps &g)
{
DB_GEN_C
QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE);
diff --git a/src/docbookgen.h b/src/docbookgen.h
index 08255a1..8f71722 100644
--- a/src/docbookgen.h
+++ b/src/docbookgen.h
@@ -49,7 +49,7 @@ class DocbookCodeGenerator : public CodeOutputInterface
void writeCodeAnchor(const char *);
void writeLineNumber(const char *extRef,const char *compId,
const char *anchorId,int l);
- void setCurrentDoc(Definition *,const char *,bool);
+ void setCurrentDoc(const Definition *,const char *,bool);
void addWord(const char *,bool);
void finish();
void startCodeFragment();
@@ -137,7 +137,7 @@ class DocbookGenerator : public OutputGenerator
{ m_codeGen.writeCodeAnchor(anchor); }
// ---------------------------
- void writeDoc(DocNode *,Definition *ctx,MemberDef *md);
+ void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md);
///////////////////////////////////////////////////////////////
// structural output interface
@@ -281,16 +281,16 @@ class DocbookGenerator : public OutputGenerator
void startClassDiagram();
void endClassDiagram(const ClassDiagram &,const char *,const char *);
void startDotGraph();
- void endDotGraph(const DotClassGraph &g);
+ void endDotGraph(DotClassGraph &g);
void startInclDepGraph();
- void endInclDepGraph(const DotInclDepGraph &g);
+ void endInclDepGraph(DotInclDepGraph &g);
void startGroupCollaboration();
- void endGroupCollaboration(const DotGroupCollaboration &g);
+ void endGroupCollaboration(DotGroupCollaboration &g);
void startCallGraph();
- void endCallGraph(const DotCallGraph &g);
+ void endCallGraph(DotCallGraph &g);
void startDirDepGraph();
- void endDirDepGraph(const DotDirDeps &g);
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &g){DB_GEN_NEW};
+ void endDirDepGraph(DotDirDeps &g);
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &g){DB_GEN_NEW};
void startQuickIndices(){DB_GEN_EMPTY};
void endQuickIndices(){DB_GEN_EMPTY};
void writeSplitBar(const char *){DB_GEN_EMPTY};
@@ -339,7 +339,7 @@ class DocbookGenerator : public OutputGenerator
void writeLabel(const char *,bool);
void endLabels();
- void setCurrentDoc(Definition *,const char *,bool) {DB_GEN_EMPTY}
+ void setCurrentDoc(const Definition *,const char *,bool) {DB_GEN_EMPTY}
void addWord(const char *,bool) {DB_GEN_EMPTY}
private:
diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp
index 64425c6..1901454 100644
--- a/src/docbookvisitor.cpp
+++ b/src/docbookvisitor.cpp
@@ -472,20 +472,22 @@ DB_VIS_C
pushEnabled();
m_hide = TRUE;
}
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
if (op->type()!=DocIncOperator::Skip)
{
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(m_ci,op->context(),
op->text(),langExt,op->isExample(),
op->exampleFile(),
@@ -634,152 +636,152 @@ DB_VIS_C
case DocSimpleSect::See:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << "</title>" << endl;
}
break;
case DocSimpleSect::Return:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trReturns()<< ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trReturns()<< "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << "</title>" << endl;
}
break;
case DocSimpleSect::Author:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << "</title>" << endl;
}
break;
case DocSimpleSect::Authors:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << "</title>" << endl;
}
break;
case DocSimpleSect::Version:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trVersion() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trVersion() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << "</title>" << endl;
}
break;
case DocSimpleSect::Since:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trSince() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trSince() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << "</title>" << endl;
}
break;
case DocSimpleSect::Date:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trDate() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trDate() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << "</title>" << endl;
}
break;
case DocSimpleSect::Note:
if (m_insidePre)
{
- m_t << "<note><title>" << theTranslator->trNote() << ": </title>" << endl;
+ m_t << "<note><title>" << theTranslator->trNote() << "</title>" << endl;
}
else
{
- m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << ": </title>" << endl;
+ m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << "</title>" << endl;
}
break;
case DocSimpleSect::Warning:
if (m_insidePre)
{
- m_t << "<warning><title>" << theTranslator->trWarning() << ": </title>" << endl;
+ m_t << "<warning><title>" << theTranslator->trWarning() << "</title>" << endl;
}
else
{
- m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << ": </title>" << endl;
+ m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << "</title>" << endl;
}
break;
case DocSimpleSect::Pre:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trPrecondition() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trPrecondition() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << "</title>" << endl;
}
break;
case DocSimpleSect::Post:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trPostcondition() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trPostcondition() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << "</title>" << endl;
}
break;
case DocSimpleSect::Copyright:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trCopyright() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trCopyright() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << "</title>" << endl;
}
break;
case DocSimpleSect::Invar:
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trInvariant() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trInvariant() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << "</title>" << endl;
}
break;
case DocSimpleSect::Remark:
// <remark> is miising the <title> possibility
if (m_insidePre)
{
- m_t << "<formalpara><title>" << theTranslator->trRemarks() << ": </title>" << endl;
+ m_t << "<formalpara><title>" << theTranslator->trRemarks() << "</title>" << endl;
}
else
{
- m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << ": </title>" << endl;
+ m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << "</title>" << endl;
}
break;
case DocSimpleSect::Attention:
if (m_insidePre)
{
- m_t << "<caution><title>" << theTranslator->trAttention() << ": </title>" << endl;
+ m_t << "<caution><title>" << theTranslator->trAttention() << "</title>" << endl;
}
else
{
- m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << ": </title>" << endl;
+ m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << "</title>" << endl;
}
break;
case DocSimpleSect::User:
@@ -1521,22 +1523,6 @@ DB_VIS_C
m_t << " ";
}
-void DocbookDocVisitor::visitPre(DocCopy *)
-{
-DB_VIS_C
- if (m_hide) return;
- // TODO: to be implemented
-}
-
-
-void DocbookDocVisitor::visitPost(DocCopy *)
-{
-DB_VIS_C
- if (m_hide) return;
- // TODO: to be implemented
-}
-
-
void DocbookDocVisitor::visitPre(DocText *)
{
DB_VIS_C
diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h
index 24b1fbb..47275f7 100644
--- a/src/docbookvisitor.h
+++ b/src/docbookvisitor.h
@@ -127,8 +127,6 @@ class DocbookDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
diff --git a/src/docgroup.cpp b/src/docgroup.cpp
new file mode 100644
index 0000000..2dcca70
--- /dev/null
+++ b/src/docgroup.cpp
@@ -0,0 +1,212 @@
+#include "doxygen.h"
+#include "util.h"
+#include "entry.h"
+#include "message.h"
+#include "docgroup.h"
+
+
+void DocGroup::enterFile(const char *fileName,int)
+{
+ m_openCount = 0;
+ m_autoGroupStack.setAutoDelete(TRUE);
+ m_autoGroupStack.clear();
+ m_memberGroupId = DOX_NOGROUP;
+ m_memberGroupDocs.resize(0);
+ m_memberGroupRelates.resize(0);
+ m_compoundName=fileName;
+}
+
+void DocGroup::leaveFile(const char *fileName,int line)
+{
+ //if (m_memberGroupId!=DOX_NOGROUP)
+ //{
+ // warn(fileName,line,"end of file while inside a member group\n");
+ //}
+ m_memberGroupId=DOX_NOGROUP;
+ m_memberGroupRelates.resize(0);
+ m_memberGroupDocs.resize(0);
+ if (!m_autoGroupStack.isEmpty())
+ {
+ warn(fileName,line,"end of file while inside a group");
+ }
+ else if (m_openCount > 0) // < 0 is already handled on close call
+ {
+ warn(fileName,line,"end of file with unbalanced grouping commands");
+ }
+}
+
+void DocGroup::enterCompound(const char *fileName,int line,const char *name)
+{
+ if (m_memberGroupId!=DOX_NOGROUP)
+ {
+ warn(fileName,line,"try to put compound %s inside a member group\n",name);
+ }
+ m_memberGroupId=DOX_NOGROUP;
+ m_memberGroupRelates.resize(0);
+ m_memberGroupDocs.resize(0);
+ m_compoundName = name;
+ int i = m_compoundName.find('(');
+ if (i!=-1)
+ {
+ m_compoundName=m_compoundName.left(i); // strip category (Obj-C)
+ }
+ if (m_compoundName.isEmpty())
+ {
+ m_compoundName=fileName;
+ }
+ //printf("groupEnterCompound(%s)\n",name);
+}
+
+void DocGroup::leaveCompound(const char *,int,const char * /*name*/)
+{
+ //printf("groupLeaveCompound(%s)\n",name);
+ //if (m_memberGroupId!=DOX_NOGROUP)
+ //{
+ // warn(fileName,line,"end of compound %s while inside a member group\n",name);
+ //}
+ m_memberGroupId=DOX_NOGROUP;
+ m_memberGroupRelates.resize(0);
+ m_memberGroupDocs.resize(0);
+ m_compoundName.resize(0);
+}
+
+int DocGroup::findExistingGroup(int &groupId,const MemberGroupInfo *info)
+{
+ //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data());
+ QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict);
+ MemberGroupInfo *mi;
+ for (di.toFirst();(mi=di.current());++di)
+ {
+ if (m_compoundName==mi->compoundName && // same file or scope
+ !mi->header.isEmpty() && // not a nameless group
+ qstricmp(mi->header,info->header)==0 // same header name
+ )
+ {
+ //printf("Found it!\n");
+ return (int)di.currentKey(); // put the item in this group
+ }
+ }
+ groupId++; // start new group
+ return groupId;
+}
+
+void DocGroup::open(Entry *e,const char *,int, bool implicit)
+{
+ if (!implicit) m_openCount++;
+ //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%d\n",
+ // e->name.data(),e->section,m_autoGroupStack.count());
+ if (e->section==Entry::GROUPDOC_SEC) // auto group
+ {
+ m_autoGroupStack.push(new Grouping(e->name,e->groupingPri()));
+ }
+ else // start of a member group
+ {
+ //printf(" membergroup id=%d %s\n",m_memberGroupId,m_memberGroupHeader.data());
+ if (m_memberGroupId==DOX_NOGROUP) // no group started yet
+ {
+ static int curGroupId=0;
+
+ MemberGroupInfo *info = new MemberGroupInfo;
+ info->header = m_memberGroupHeader.stripWhiteSpace();
+ info->compoundName = m_compoundName;
+ m_memberGroupId = findExistingGroup(curGroupId,info);
+ //printf(" use membergroup %d\n",m_memberGroupId);
+ Doxygen::memGrpInfoDict.insert(m_memberGroupId,info);
+
+ m_memberGroupRelates = e->relates;
+ e->mGrpId = m_memberGroupId;
+ }
+ }
+}
+
+void DocGroup::close(Entry *e,const char *fileName,int line,bool foundInline)
+{
+ if (m_openCount < 1)
+ {
+ warn(fileName,line,"unbalanced grouping commands");
+ }
+ else
+ {
+ m_openCount--;
+ }
+ //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%d\n",
+ // e->name.data(),e->section,fileName,line,m_autoGroupStack.count());
+ if (m_memberGroupId!=DOX_NOGROUP) // end of member group
+ {
+ MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId);
+ if (info) // known group
+ {
+ info->doc = m_memberGroupDocs;
+ info->docFile = fileName;
+ info->docLine = line;
+ }
+ m_memberGroupId=DOX_NOGROUP;
+ m_memberGroupRelates.resize(0);
+ m_memberGroupDocs.resize(0);
+ if (!foundInline) e->mGrpId=DOX_NOGROUP;
+ //printf("new group id=%d\n",m_memberGroupId);
+ }
+ else if (!m_autoGroupStack.isEmpty()) // end of auto group
+ {
+ Grouping *grp = m_autoGroupStack.pop();
+ // see bug577005: we should not remove the last group for e
+ if (!foundInline) e->groups->removeLast();
+ //printf("Removing %s e=%p\n",grp->groupname.data(),e);
+ delete grp;
+ if (!foundInline) initGroupInfo(e);
+ }
+}
+
+void DocGroup::initGroupInfo(Entry *e)
+{
+ //printf("==> initGroup(id=%d,related=%s,e=%p)\n",m_memberGroupId,
+ // m_memberGroupRelates.data(),e);
+ e->mGrpId = m_memberGroupId;
+ e->relates = m_memberGroupRelates;
+ if (!m_autoGroupStack.isEmpty())
+ {
+ //printf("Appending group %s to %s: count=%d entry=%p\n",
+ // m_autoGroupStack.top()->groupname.data(),
+ // e->name.data(),e->groups->count(),e);
+ e->groups->append(new Grouping(*m_autoGroupStack.top()));
+ }
+}
+
+void DocGroup::addDocs(Entry *e)
+{
+ if (e->section==Entry::MEMBERGRP_SEC)
+ {
+ m_memberGroupDocs=e->brief.stripWhiteSpace();
+ e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine);
+ if (!m_memberGroupDocs.isEmpty() && !e->doc.isEmpty())
+ {
+ m_memberGroupDocs+="\n\n";
+ }
+ m_memberGroupDocs+=e->doc;
+ MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId);
+ if (info)
+ {
+ info->doc = m_memberGroupDocs;
+ info->docFile = e->docFile;
+ info->docLine = e->docLine;
+ info->setRefItems(e->sli);
+ }
+ e->doc.resize(0);
+ e->brief.resize(0);
+ }
+}
+
+bool DocGroup::isEmpty() const
+{
+ return (m_memberGroupId==DOX_NOGROUP);
+}
+
+void DocGroup::clearHeader()
+{
+ m_memberGroupHeader.resize(0);
+}
+
+void DocGroup::appendHeader(const char text)
+{
+ m_memberGroupHeader += text;
+}
diff --git a/src/docgroup.h b/src/docgroup.h
new file mode 100644
index 0000000..4ce9af9
--- /dev/null
+++ b/src/docgroup.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2019 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.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#ifndef DOCGROUP_H
+#define DOCGROUP_H
+
+#include <qstack.h>
+#include <qstring.h>
+#include "membergroup.h"
+
+class Entry;
+
+class DocGroup
+{
+ public:
+ DocGroup() {};
+
+ public:
+ void enterFile(const char *fileName,int);
+ void leaveFile(const char *fileName,int line);
+ void enterCompound(const char *fileName,int line,const char *name);
+ void leaveCompound(const char *,int,const char * /*name*/);
+ void open(Entry *e,const char *,int,bool implicit=false);
+ void close(Entry *e,const char *fileName,int line,bool foundInline);
+ void initGroupInfo(Entry *e);
+ bool isEmpty() const;
+ void clearHeader();
+ void appendHeader(const char);
+ void addDocs(Entry *e);
+
+ private:
+ int findExistingGroup(int &groupId,const MemberGroupInfo *info);
+ int m_openCount;
+ QCString m_memberGroupHeader;
+ int m_memberGroupId;
+ QCString m_memberGroupRelates;
+ QCString m_memberGroupDocs;
+ QStack<Grouping> m_autoGroupStack;
+ QCString m_compoundName;
+};
+
+#endif
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 1c8479b..be0d60b 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -87,7 +87,7 @@ static const char *sectionLevelToName[] =
//---------------------------------------------------------------------------
// Parser state: global variables during a call to validatingParseDoc
-static Definition * g_scope;
+static const Definition * g_scope;
static QCString g_context;
static bool g_inSeeBlock;
static bool g_xmlComment;
@@ -102,7 +102,7 @@ static QCString g_relPath;
static bool g_hasParamCommand;
static bool g_hasReturnCommand;
static QDict<void> g_paramsFound;
-static MemberDef * g_memberDef;
+static const MemberDef * g_memberDef;
static bool g_isExample;
static QCString g_exampleName;
static SectionDict * g_sectionDict;
@@ -120,7 +120,7 @@ static bool g_includeFileShowLineNo;
*/
struct DocParserContext
{
- Definition *scope;
+ const Definition *scope;
QCString context;
bool inSeeBlock;
bool xmlComment;
@@ -135,7 +135,7 @@ struct DocParserContext
bool hasParamCommand;
bool hasReturnCommand;
- MemberDef * memberDef;
+ const MemberDef * memberDef;
QDict<void> paramsFound;
bool isExample;
QCString exampleName;
@@ -406,9 +406,9 @@ static void checkArgumentName(const QCString &name,bool isParam)
{
if (!Config_getBool(WARN_IF_DOC_ERROR)) return;
if (g_memberDef==0) return; // not a member
- ArgumentList *al=g_memberDef->isDocsForDefinition() ?
- g_memberDef->argumentList() :
- g_memberDef->declArgumentList();
+ const ArgumentList *al=g_memberDef->isDocsForDefinition() ?
+ g_memberDef->argumentList() :
+ g_memberDef->declArgumentList();
SrcLangExt lang = g_memberDef->getLanguage();
//printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition());
if (al==0) return; // no argument list
@@ -421,7 +421,7 @@ static void checkArgumentName(const QCString &name,bool isParam)
if (lang==SrcLangExt_Fortran) aName=aName.lower();
//printf("aName=`%s'\n",aName.data());
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
bool found=FALSE;
for (ali.toFirst();(a=ali.current());++ali)
{
@@ -476,14 +476,14 @@ static void checkUnOrMultipleDocumentedParams()
{
if (g_memberDef && g_hasParamCommand && Config_getBool(WARN_IF_DOC_ERROR))
{
- ArgumentList *al=g_memberDef->isDocsForDefinition() ?
+ const ArgumentList *al=g_memberDef->isDocsForDefinition() ?
g_memberDef->argumentList() :
g_memberDef->declArgumentList();
SrcLangExt lang = g_memberDef->getLanguage();
if (al!=0)
{
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
bool found=FALSE;
for (ali.toFirst();(a=ali.current());++ali)
{
@@ -558,106 +558,6 @@ static void checkUnOrMultipleDocumentedParams()
}
}
-/*! Check if a member has documentation for its parameter and or return
- * type, if applicable. If found this will be stored in the member, this
- * is needed as a member can have brief and detailed documentation, while
- * only one of these needs to document the parameters.
- */
-static void detectNoDocumentedParams()
-{
- if (g_memberDef && Config_getBool(WARN_NO_PARAMDOC))
- {
- ArgumentList *al = g_memberDef->argumentList();
- ArgumentList *declAl = g_memberDef->declArgumentList();
- QCString returnType = g_memberDef->typeString();
- bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python;
-
- if (!g_memberDef->hasDocumentedParams() &&
- g_hasParamCommand)
- {
- //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
- g_memberDef->setHasDocumentedParams(TRUE);
- }
- else if (!g_memberDef->hasDocumentedParams())
- {
- bool allDoc=TRUE; // no parameter => all parameters are documented
- if ( // member has parameters
- al!=0 && // but the member has a parameter list
- al->count()>0 // with at least one parameter (that is not void)
- )
- {
- ArgumentListIterator ali(*al);
- Argument *a;
-
- // see if all parameters have documentation
- for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
- {
- if (!a->name.isEmpty() && a->type!="void" &&
- !(isPython && (a->name=="self" || a->name=="cls"))
- )
- {
- allDoc = !a->docs.isEmpty();
- }
- //printf("a->type=%s a->name=%s doc=%s\n",
- // a->type.data(),a->name.data(),a->docs.data());
- }
- if (!allDoc && declAl!=0) // try declaration arguments as well
- {
- allDoc=TRUE;
- ArgumentListIterator ali(*declAl);
- Argument *a;
- for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
- {
- if (!a->name.isEmpty() && a->type!="void" &&
- !(isPython && (a->name=="self" || a->name=="cls"))
- )
- {
- allDoc = !a->docs.isEmpty();
- }
- //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data());
- }
- }
- }
- if (allDoc)
- {
- //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data());
- g_memberDef->setHasDocumentedParams(TRUE);
- }
- }
- //printf("Member %s hasDocumentedReturnType()=%d hasReturnCommand=%d\n",
- // g_memberDef->name().data(),g_memberDef->hasDocumentedReturnType(),g_hasReturnCommand);
- if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found
- g_hasReturnCommand)
- {
- g_memberDef->setHasDocumentedReturnType(TRUE);
- }
- else if ( // see if return type is documented in a function w/o return type
- g_hasReturnCommand &&
- (//returnType.isEmpty() || // empty return type
- returnType.find("void")!=-1 || // void return type
- returnType.find("subroutine")!=-1 || // fortran subroutine
- g_memberDef->isConstructor() || // a constructor
- g_memberDef->isDestructor() // or destructor
- )
- )
- {
- warn_doc_error(g_fileName,doctokenizerYYlineno,"documented empty return type of %s",g_memberDef->qualifiedName().data());
- }
- else if ( // see if return needs to documented
- g_memberDef->hasDocumentedReturnType() ||
- //returnType.isEmpty() || // empty return type
- returnType.find("void")!=-1 || // void return type
- returnType.find("subroutine")!=-1 || // fortran subroutine
- g_memberDef->isConstructor() || // a constructor
- g_memberDef->isDestructor() // or destructor
- )
- {
- g_memberDef->setHasDocumentedReturnType(TRUE);
- }
- }
-}
-
-
//---------------------------------------------------------------------------
/*! Strips known html and tex extensions from \a text. */
@@ -755,7 +655,7 @@ static bool insideTable(DocNode *n)
static bool findDocsForMemberOrCompound(const char *commandName,
QCString *pDoc,
QCString *pBrief,
- Definition **pDef)
+ const Definition **pDef)
{
//printf("findDocsForMemberOrCompound(%s)\n",commandName);
*pDoc="";
@@ -789,12 +689,12 @@ static bool findDocsForMemberOrCompound(const char *commandName,
QCString args=cmdArg.right(l-funcStart);
// try if the link is to a member
- MemberDef *md=0;
- ClassDef *cd=0;
- FileDef *fd=0;
- NamespaceDef *nd=0;
- GroupDef *gd=0;
- PageDef *pd=0;
+ const MemberDef *md=0;
+ const ClassDef *cd=0;
+ const FileDef *fd=0;
+ const NamespaceDef *nd=0;
+ const GroupDef *gd=0;
+ const PageDef *pd=0;
bool found = getDefs(
g_context.find('.')==-1?g_context.data():"", // `find('.') is a hack to detect files
name,
@@ -916,8 +816,8 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return tok;
}
while ((tok=doctokenizerYYlex()) &&
@@ -952,7 +852,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children,
break;
}
}
- DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok));
+ DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok));
return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST
) ? tok : RetVal_OK;
}
@@ -1125,8 +1025,8 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor
// ------- try to turn the word 'name' into a link
- Definition *compound=0;
- MemberDef *member=0;
+ const Definition *compound=0;
+ const MemberDef *member=0;
int len = g_token->name.length();
ClassDef *cd=0;
bool ambig;
@@ -1165,7 +1065,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor
}
else if (compound->definitionType()==Definition::TypeGroup)
{
- name=(dynamic_cast<GroupDef*>(compound))->groupTitle();
+ name=(dynamic_cast<const GroupDef*>(compound))->groupTitle();
}
children.append(new
DocLinkedWord(parent,name,
@@ -1177,7 +1077,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor
);
}
else if (compound->definitionType()==Definition::TypeFile &&
- (dynamic_cast<FileDef*>(compound))->generateSourceFile()
+ (dynamic_cast<const FileDef*>(compound))->generateSourceFile()
) // undocumented file that has source code we can link to
{
children.append(new
@@ -1262,7 +1162,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent)
QCString tokenName = g_token->name;
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(tokenName));
return 0;
}
@@ -1282,7 +1182,7 @@ static DocAnchor *handleAnchor(DocNode *parent)
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(g_token->name));
return 0;
}
@@ -2063,7 +1963,7 @@ void DocIncOperator::parse()
if (g_includeFileName.isEmpty())
{
warn_doc_error(g_fileName,doctokenizerYYlineno,
- "No previous '\\include' or \\dontinclude' command for '\\%s' present",
+ "No previous '\\include' or '\\dontinclude' command for '\\%s' present",
typeAsString());
}
@@ -2198,100 +2098,6 @@ void DocIncOperator::parse()
//---------------------------------------------------------------------------
-void DocCopy::parse(QList<DocNode> &children)
-{
- QCString doc,brief;
- Definition *def;
- if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def))
- {
- if (g_copyStack.findRef(def)==-1) // definition not parsed earlier
- {
- bool hasParamCommand = g_hasParamCommand;
- bool hasReturnCommand = g_hasReturnCommand;
- QDict<void> paramsFound = g_paramsFound;
- //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
- // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
-
- docParserPushContext(FALSE);
- g_scope = def;
- if (def->definitionType()==Definition::TypeMember && def->getOuterScope())
- {
- if (def->getOuterScope()!=Doxygen::globalScope)
- {
- g_context=def->getOuterScope()->name();
- }
- }
- else if (def!=Doxygen::globalScope)
- {
- g_context=def->name();
- }
- g_styleStack.clear();
- g_nodeStack.clear();
- g_paramsFound.clear();
- g_copyStack.append(def);
- // make sure the descriptions end with a newline, so the parser will correctly
- // handle them in all cases.
- //printf("doc='%s'\n",doc.data());
- //printf("brief='%s'\n",brief.data());
- if (m_copyBrief)
- {
- brief+='\n';
- internalValidatingParseDoc(m_parent,children,brief);
-
- //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
- // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
- hasParamCommand = hasParamCommand || g_hasParamCommand;
- hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
- QDictIterator<void> it(g_paramsFound);
- void *item;
- for (;(item=it.current());++it)
- {
- paramsFound.insert(it.currentKey(),it.current());
- }
- }
- if (m_copyDetails)
- {
- doc+='\n';
- internalValidatingParseDoc(m_parent,children,doc);
-
- //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
- // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
- hasParamCommand = hasParamCommand || g_hasParamCommand;
- hasReturnCommand = hasReturnCommand || g_hasReturnCommand;
- QDictIterator<void> it(g_paramsFound);
- void *item;
- for (;(item=it.current());++it)
- {
- paramsFound.insert(it.currentKey(),it.current());
- }
- }
- g_copyStack.remove(def);
- ASSERT(g_styleStack.isEmpty());
- ASSERT(g_nodeStack.isEmpty());
- docParserPopContext(TRUE);
-
- g_hasParamCommand = hasParamCommand;
- g_hasReturnCommand = hasReturnCommand;
- g_paramsFound = paramsFound;
-
- //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n",
- // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count());
- }
- else // oops, recursion
- {
- warn_doc_error(g_fileName,doctokenizerYYlineno,"recursive call chain of \\copydoc commands detected at %d\n",
- doctokenizerYYlineno);
- }
- }
- else
- {
- warn_doc_error(g_fileName,doctokenizerYYlineno,"target %s of \\copydoc command not found",
- qPrint(m_link));
- }
-}
-
-//---------------------------------------------------------------------------
-
DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) :
m_id(id), m_key(key), m_relPath(g_relPath)
{
@@ -2547,7 +2353,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
m_refType(Unknown), m_isSubPage(FALSE)
{
m_parent = parent;
- Definition *compound = 0;
+ const Definition *compound = 0;
QCString anchor;
//printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data());
ASSERT(!target.isEmpty());
@@ -2600,16 +2406,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
{
if (anchor.isEmpty() && /* compound link */
compound->definitionType()==Definition::TypeGroup && /* is group */
- (dynamic_cast<GroupDef *>(compound))->groupTitle() /* with title */
+ (dynamic_cast<const GroupDef *>(compound))->groupTitle() /* with title */
)
{
- m_text=(dynamic_cast<GroupDef *>(compound))->groupTitle(); // use group's title as link
+ m_text=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link
}
else if (compound->definitionType()==Definition::TypeMember &&
- (dynamic_cast<MemberDef*>(compound))->isObjCMethod())
+ (dynamic_cast<const MemberDef*>(compound))->isObjCMethod())
{
// Objective C Method
- MemberDef *member = dynamic_cast<MemberDef*>(compound);
+ const MemberDef *member = dynamic_cast<const MemberDef*>(compound);
bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE;
m_text = member->objCMethodName(localLink,g_inSeeBlock);
}
@@ -2621,7 +2427,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
return;
}
else if (compound && compound->definitionType()==Definition::TypeFile &&
- (dynamic_cast<FileDef*>(compound))->generateSourceFile()
+ (dynamic_cast<const FileDef*>(compound))->generateSourceFile()
) // undocumented file that has source code we can link to
{
m_file = compound->getSourceFileBase();
@@ -2743,7 +2549,7 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont
DocLink::DocLink(DocNode *parent,const QCString &target)
{
m_parent = parent;
- Definition *compound = 0;
+ const Definition *compound = 0;
QCString anchor;
m_refText = target;
m_relPath = g_relPath;
@@ -2761,7 +2567,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target)
m_ref = compound->getReference();
}
else if (compound && compound->definitionType()==Definition::TypeFile &&
- (dynamic_cast<FileDef*>(compound))->generateSourceFile()
+ (dynamic_cast<const FileDef*>(compound))->generateSourceFile()
) // undocumented file that has source code we can link to
{
m_file = compound->getSourceFileBase();
@@ -2875,8 +2681,9 @@ DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &cont
m_parent = parent;
}
-void DocDotFile::parse()
+bool DocDotFile::parse()
{
+ bool ok = false;
defaultHandleTitleAndSize(CMD_DOTFILE,this,m_children,m_width,m_height);
bool ambig;
@@ -2888,6 +2695,7 @@ void DocDotFile::parse()
if (fd)
{
m_file = fd->absFilePath();
+ ok = true;
}
else if (ambig)
{
@@ -2901,6 +2709,7 @@ void DocDotFile::parse()
warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found "
"in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name));
}
+ return ok;
}
DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) :
@@ -2909,8 +2718,9 @@ DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &cont
m_parent = parent;
}
-void DocMscFile::parse()
+bool DocMscFile::parse()
{
+ bool ok = false;
defaultHandleTitleAndSize(CMD_MSCFILE,this,m_children,m_width,m_height);
bool ambig;
@@ -2922,6 +2732,7 @@ void DocMscFile::parse()
if (fd)
{
m_file = fd->absFilePath();
+ ok = true;
}
else if (ambig)
{
@@ -2935,6 +2746,7 @@ void DocMscFile::parse()
warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found "
"in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name));
}
+ return ok;
}
//---------------------------------------------------------------------------
@@ -2945,8 +2757,9 @@ DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &cont
m_parent = parent;
}
-void DocDiaFile::parse()
+bool DocDiaFile::parse()
{
+ bool ok = false;
defaultHandleTitleAndSize(CMD_DIAFILE,this,m_children,m_width,m_height);
bool ambig;
@@ -2958,6 +2771,7 @@ void DocDiaFile::parse()
if (fd)
{
m_file = fd->absFilePath();
+ ok = true;
}
else if (ambig)
{
@@ -2971,6 +2785,7 @@ void DocDiaFile::parse()
warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found "
"in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name));
}
+ return ok;
}
//---------------------------------------------------------------------------
@@ -3019,7 +2834,11 @@ DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString
bool DocImage::isSVG() const
{
- return m_url.isEmpty() ? m_name.right(4)==".svg" : m_url.right(4)==".svg";
+ QCString locName = m_url.isEmpty() ? m_name : m_url;
+ int len = locName.length();
+ int fnd = locName.find('?'); // ignore part from ? until end
+ if (fnd!=-1) fnd=len;
+ return fnd>=4 && locName.mid(fnd-4,4)==".svg";
}
void DocImage::parse()
@@ -4739,8 +4558,8 @@ int DocParamList::parse(const QCString &cmdName)
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
retval=0;
goto endparamlist;
}
@@ -4778,7 +4597,7 @@ int DocParamList::parse(const QCString &cmdName)
if (tok==0) /* premature end of comment block */
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
- "argument of command %s",qPrint(cmdName));
+ "argument of command %s",qPrint(saveCmdName));
retval=0;
goto endparamlist;
}
@@ -4976,7 +4795,7 @@ void DocPara::handleCite()
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint("cite"));
return;
}
@@ -5008,7 +4827,7 @@ void DocPara::handleEmoji()
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint("emoji"));
return;
}
@@ -5055,12 +4874,13 @@ int DocPara::handleXRefItem()
void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t)
{
- DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName)));
+ QCString saveCmdName = cmdName;
+ DBG(("handleIncludeOperator(%s)\n",qPrint(saveCmdName)));
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
doctokenizerYYsetStatePattern();
@@ -5069,13 +4889,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type
if (tok==0)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
- "argument of command %s", qPrint(cmdName));
+ "argument of command %s", qPrint(saveCmdName));
return;
}
else if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName);
@@ -5141,7 +4961,7 @@ void DocPara::handleImage(const QCString &cmdName)
tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command with option",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option",
qPrint(saveCmdName));
return;
}
@@ -5149,7 +4969,7 @@ void DocPara::handleImage(const QCString &cmdName)
}
else
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(saveCmdName));
return;
}
@@ -5164,7 +4984,7 @@ void DocPara::handleImage(const QCString &cmdName)
tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
qPrint(saveCmdName));
return;
}
@@ -5199,11 +5019,12 @@ void DocPara::handleImage(const QCString &cmdName)
template<class T>
void DocPara::handleFile(const QCString &cmdName)
{
+ QCString saveCmdName = cmdName;
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
doctokenizerYYsetStateFile();
@@ -5212,13 +5033,19 @@ void DocPara::handleFile(const QCString &cmdName)
if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
QCString name = g_token->name;
T *df = new T(this,name,g_context);
- m_children.append(df);
- df->parse();
+ if (df->parse())
+ {
+ m_children.append(df);
+ }
+ else
+ {
+ delete df;
+ }
}
void DocPara::handleVhdlFlow()
@@ -5230,11 +5057,12 @@ void DocPara::handleVhdlFlow()
void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
{
+ QCString saveCmdName = cmdName;
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
doctokenizerYYsetStateLink();
@@ -5242,7 +5070,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
doctokenizerYYsetStatePara();
@@ -5257,12 +5085,13 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink)
void DocPara::handleRef(const QCString &cmdName)
{
- DBG(("handleRef(%s)\n",qPrint(cmdName)));
+ QCString saveCmdName = cmdName;
+ DBG(("handleRef(%s)\n",qPrint(saveCmdName)));
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
doctokenizerYYsetStateRef();
@@ -5271,7 +5100,7 @@ void DocPara::handleRef(const QCString &cmdName)
if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
goto endref;
}
ref = new DocRef(this,g_token->name,g_context);
@@ -5284,6 +5113,7 @@ endref:
void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
{
DBG(("handleInclude(%s)\n",qPrint(cmdName)));
+ QCString saveCmdName = cmdName;
int tok=doctokenizerYYlex();
bool isBlock = false;
if (tok==TK_WORD && g_token->name=="{")
@@ -5324,8 +5154,8 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
}
else if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
doctokenizerYYsetStateFile();
@@ -5334,13 +5164,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
if (tok==0)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
- "argument of command %s",qPrint(cmdName));
+ "argument of command %s",qPrint(saveCmdName));
return;
}
else if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
QCString fileName = g_token->name;
@@ -5354,7 +5184,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
if (tok!=TK_WORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
blockId = "["+g_token->name+"]";
@@ -5388,25 +5218,26 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t)
void DocPara::handleSection(const QCString &cmdName)
{
+ QCString saveCmdName = cmdName;
// get the argument of the section command.
int tok=doctokenizerYYlex();
if (tok!=TK_WHITESPACE)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command",
- qPrint(cmdName));
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command",
+ qPrint(saveCmdName));
return;
}
tok=doctokenizerYYlex();
if (tok==0)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the "
- "argument of command %s\n", qPrint(cmdName));
+ "argument of command %s\n", qPrint(saveCmdName));
return;
}
else if (tok!=TK_WORD && tok!=TK_LNKWORD)
{
warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s",
- tokToString(tok),qPrint(cmdName));
+ tokToString(tok),qPrint(saveCmdName));
return;
}
g_token->sectionId = g_token->name;
@@ -5464,7 +5295,7 @@ void DocPara::handleInheritDoc()
MemberDef *reMd = g_memberDef->reimplements();
if (reMd) // member from which was inherited.
{
- MemberDef *thisMd = g_memberDef;
+ const MemberDef *thisMd = g_memberDef;
//printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data());
docParserPushContext();
g_scope=reMd->getOuterScope();
@@ -6981,54 +6812,55 @@ int DocSection::parse()
//printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel);
- if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1)
+ while (true)
{
- // then parse any number of nested sections
- while (retval==RetVal_Subsection) // more sections follow
+ if (retval==RetVal_Subsection && m_level<=Doxygen::subpageNestingLevel+1)
{
- //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
- DocSection *s=new DocSection(this,
- QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
- m_children.append(s);
- retval = s->parse();
+ // then parse any number of nested sections
+ while (retval==RetVal_Subsection) // more sections follow
+ {
+ //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
+ DocSection *s=new DocSection(this,
+ QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ break;
}
- }
- else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2)
- {
- // then parse any number of nested sections
- while (retval==RetVal_Subsubsection) // more sections follow
+ else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2)
{
- //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
- DocSection *s=new DocSection(this,
- QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
- m_children.append(s);
- retval = s->parse();
+ if ((m_level<=1+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md"))
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]);
+ // then parse any number of nested sections
+ while (retval==RetVal_Subsubsection) // more sections follow
+ {
+ //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
+ DocSection *s=new DocSection(this,
+ QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ if (!(m_level<Doxygen::subpageNestingLevel+2 && retval == RetVal_Subsection)) break;
}
- }
- else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3))
- {
- // then parse any number of nested sections
- while (retval==RetVal_Paragraph) // more sections follow
+ else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3))
{
- //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
- DocSection *s=new DocSection(this,
- QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
- m_children.append(s);
- retval = s->parse();
+ if ((m_level<=2+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md"))
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]);
+ // then parse any number of nested sections
+ while (retval==RetVal_Paragraph) // more sections follow
+ {
+ //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId];
+ DocSection *s=new DocSection(this,
+ QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break;
+ }
+ else
+ {
+ break;
}
- }
- else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) ||
- (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph)
- )
- {
- int level = (retval==RetVal_Subsubsection) ? 3 : 4;
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s "
- "command found inside %s!",
- sectionLevelToName[level],sectionLevelToName[m_level]);
- retval=0; // stop parsing
- }
- else
- {
}
INTERNAL_ASSERT(retval==0 ||
@@ -7182,21 +7014,72 @@ void DocRoot::parse()
{
delete par;
}
- if (retval==TK_LISTITEM)
+ if (retval==RetVal_Paragraph)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
+ if (!QString(g_token->sectionId).startsWith("autotoc_md"))
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!");
+ while (retval==RetVal_Paragraph)
+ {
+ SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId);
+ if (sec)
+ {
+ DocSection *s=new DocSection(this,
+ QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id `%s'; ignoring paragraph",qPrint(g_token->sectionId));
+ retval = 0;
+ }
+ }
}
- else if (retval==RetVal_Subsection)
+ if (retval==RetVal_Subsubsection)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!");
+ if (!(QString(g_token->sectionId).startsWith("autotoc_md")))
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!");
+ while (retval==RetVal_Subsubsection)
+ {
+ SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId);
+ if (sec)
+ {
+ DocSection *s=new DocSection(this,
+ QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id `%s'; ignoring subsubsection",qPrint(g_token->sectionId));
+ retval = 0;
+ }
+ }
}
- else if (retval==RetVal_Subsubsection)
+ if (retval==RetVal_Subsection)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!");
+ if (!(QString(g_token->sectionId).startsWith("autotoc_md")))
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!");
+ while (retval==RetVal_Subsection)
+ {
+ SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId);
+ if (sec)
+ {
+ DocSection *s=new DocSection(this,
+ QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId);
+ m_children.append(s);
+ retval = s->parse();
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id `%s'; ignoring subsection",qPrint(g_token->sectionId));
+ retval = 0;
+ }
+ }
}
- else if (retval==RetVal_Paragraph)
+ if (retval==TK_LISTITEM)
{
- warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!");
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found");
}
if (retval==RetVal_Internal)
{
@@ -7366,7 +7249,7 @@ static QCString processCopyDoc(const char *data,uint &len)
while (j<len && (data[j]==' ' || data[j]=='\t')) j++;
// extract the argument
QCString id = extractCopyDocId(data,j,len);
- Definition *def;
+ const Definition *def = 0;
QCString doc,brief;
//printf("resolving docs='%s'\n",id.data());
if (findDocsForMemberOrCompound(id,&doc,&brief,&def))
@@ -7555,7 +7438,7 @@ QCString getJsDirEmbedingChar(QString::Direction textDir)
//---------------------------------------------------------------------------
DocRoot *validatingParseDoc(const char *fileName,int startLine,
- Definition *ctx,MemberDef *md,
+ const Definition *ctx,const MemberDef *md,
const char *input,bool indexWords,
bool isExample, const char *exampleName,
bool singleLine, bool linkFromIndex)
@@ -7581,12 +7464,12 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine,
}
else if (ctx && ctx->definitionType()==Definition::TypePage)
{
- Definition *scope = (dynamic_cast<PageDef*>(ctx))->getPageScope();
+ const Definition *scope = (dynamic_cast<const PageDef*>(ctx))->getPageScope();
if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
}
else if (ctx && ctx->definitionType()==Definition::TypeGroup)
{
- Definition *scope = (dynamic_cast<GroupDef*>(ctx))->getGroupScope();
+ const Definition *scope = (dynamic_cast<const GroupDef*>(ctx))->getGroupScope();
if (scope && scope!=Doxygen::globalScope) g_context = scope->name();
}
else
@@ -7740,7 +7623,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine,
}
checkUnOrMultipleDocumentedParams();
- detectNoDocumentedParams();
+ if (g_memberDef) g_memberDef->detectUndocumentedParams(g_hasParamCommand,g_hasReturnCommand);
// TODO: These should be called at the end of the program.
//doctokenizerYYcleanup();
diff --git a/src/docparser.h b/src/docparser.h
index 15180f9..cab1589 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -65,7 +65,7 @@ QCString getJsDirEmbedingChar(QString::Direction textDir);
* pointer is handed over to the caller.
*/
DocRoot *validatingParseDoc(const char *fileName,int startLine,
- Definition *context, MemberDef *md,
+ const Definition *context, const MemberDef *md,
const char *input,bool indexWords,
bool isExample,const char *exampleName=0,
bool singleLine=FALSE,bool linkFromIndex=FALSE);
@@ -677,41 +677,23 @@ class DocFormula : public DocNode
class DocIndexEntry : public DocNode
{
public:
- DocIndexEntry(DocNode *parent,Definition *scope,MemberDef *md)
+ DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md)
: m_scope(scope), m_member(md){ m_parent = parent; }
Kind kind() const { return Kind_IndexEntry; }
int parse();
- Definition *scope() const { return m_scope; }
- MemberDef *member() const { return m_member; }
+ const Definition *scope() const { return m_scope; }
+ const MemberDef *member() const { return m_member; }
QCString entry() const { return m_entry; }
void accept(DocVisitor *v) { v->visit(this); }
private:
QCString m_entry;
- Definition *m_scope;
- MemberDef *m_member;
+ const Definition *m_scope;
+ const MemberDef *m_member;
};
//-----------------------------------------------------------------------
-/** Node representing a copy of documentation block. */
-class DocCopy : public DocNode
-{
- public:
- DocCopy(DocNode *parent,const QCString &link,bool copyBrief,bool copyDetails)
- : m_link(link),
- m_copyBrief(copyBrief), m_copyDetails(copyDetails) { m_parent = parent; }
- Kind kind() const { return Kind_Copy; }
- QCString link() const { return m_link; }
- void accept(DocVisitor * /*v*/) { /*CompAccept<DocCopy>::accept(this,v);*/ }
- void parse(QList<DocNode> &children);
-
- private:
- QCString m_link;
- bool m_copyBrief;
- bool m_copyDetails;
-};
-
/** Node representing an auto List */
class DocAutoList : public CompAccept<DocAutoList>
{
@@ -816,7 +798,7 @@ class DocDotFile : public CompAccept<DocDotFile>
{
public:
DocDotFile(DocNode *parent,const QCString &name,const QCString &context);
- void parse();
+ bool parse();
Kind kind() const { return Kind_DotFile; }
QCString name() const { return m_name; }
QCString file() const { return m_file; }
@@ -839,7 +821,7 @@ class DocMscFile : public CompAccept<DocMscFile>
{
public:
DocMscFile(DocNode *parent,const QCString &name,const QCString &context);
- void parse();
+ bool parse();
Kind kind() const { return Kind_MscFile; }
QCString name() const { return m_name; }
QCString file() const { return m_file; }
@@ -862,7 +844,7 @@ class DocDiaFile : public CompAccept<DocDiaFile>
{
public:
DocDiaFile(DocNode *parent,const QCString &name,const QCString &context);
- void parse();
+ bool parse();
Kind kind() const { return Kind_DiaFile; }
QCString name() const { return m_name; }
QCString file() const { return m_file; }
diff --git a/src/docsets.cpp b/src/docsets.cpp
index 1d79c9d..055532a 100644
--- a/src/docsets.cpp
+++ b/src/docsets.cpp
@@ -236,7 +236,7 @@ void DocSets::addContentsItem(bool isDir,
const char *anchor,
bool /* separateIndex */,
bool /* addToNavIndex */,
- Definition * /*def*/)
+ const Definition * /*def*/)
{
(void)isDir;
//printf("DocSets::addContentsItem(%s) m_dc=%d\n",name,m_dc);
@@ -274,14 +274,14 @@ void DocSets::addContentsItem(bool isDir,
}
}
-void DocSets::addIndexItem(Definition *context,MemberDef *md,
+void DocSets::addIndexItem(const Definition *context,const MemberDef *md,
const char *,const char *)
{
if (md==0 && context==0) return;
- FileDef *fd = 0;
- ClassDef *cd = 0;
- NamespaceDef *nd = 0;
+ const FileDef *fd = 0;
+ const ClassDef *cd = 0;
+ const NamespaceDef *nd = 0;
if (md)
{
@@ -417,7 +417,7 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,
{
scope = nd->name();
}
- MemberDef *declMd = md->memberDeclaration();
+ const MemberDef *declMd = md->memberDeclaration();
if (declMd==0) declMd = md;
{
fd = md->getFileDef();
@@ -432,15 +432,15 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,
{
if (fd==0 && context->definitionType()==Definition::TypeFile)
{
- fd = dynamic_cast<FileDef*>(context);
+ fd = dynamic_cast<const FileDef*>(context);
}
if (cd==0 && context->definitionType()==Definition::TypeClass)
{
- cd = dynamic_cast<ClassDef*>(context);
+ cd = dynamic_cast<const ClassDef*>(context);
}
if (nd==0 && context->definitionType()==Definition::TypeNamespace)
{
- nd = dynamic_cast<NamespaceDef*>(context);
+ nd = dynamic_cast<const NamespaceDef*>(context);
}
if (fd)
{
diff --git a/src/docsets.h b/src/docsets.h
index 548ba75..0d75bfd 100644
--- a/src/docsets.h
+++ b/src/docsets.h
@@ -45,9 +45,9 @@ class DocSets : public IndexIntf
const char *anchor,
bool separateIndex,
bool addToNavIndex,
- Definition *def
+ const Definition *def
);
- void addIndexItem(Definition *context,MemberDef *md,
+ void addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor,const char *title);
void addIndexFile(const char *name);
void addImageFile(const char *) {}
diff --git a/src/doctokenizer.h b/src/doctokenizer.h
index 8b8ca97..b59fc09 100644
--- a/src/doctokenizer.h
+++ b/src/doctokenizer.h
@@ -71,9 +71,7 @@ enum Tokens
/** @brief Data associated with a token used by the comment block parser. */
struct TokenInfo
{
- // unknown token
- char unknownChar;
-
+ TokenInfo() : isEnumList(FALSE), indent(0), id(-1), endTag(FALSE), emptyTag(FALSE), paramDir(Unspecified) {}
// command token
QCString name;
diff --git a/src/doctokenizer.l b/src/doctokenizer.l
index 5cf5f02..5346c0a 100644
--- a/src/doctokenizer.l
+++ b/src/doctokenizer.l
@@ -211,7 +211,7 @@ static void handleHtmlTag()
{
char c=tagText.at(i);
// skip spaces
- while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
+ while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
// check for end of the tag
if (c == '>') break;
// Check for XML style "empty" tag.
@@ -222,17 +222,17 @@ static void handleHtmlTag()
}
startName=i;
// search for end of name
- while (i<(int)yyleng && !isspace(c) && c!='=') { c=tagText.at(++i); }
+ while (i<(int)yyleng && !isspace((uchar)c) && c!='=') { c=tagText.at(++i); }
endName=i;
HtmlAttrib opt;
opt.name = tagText.mid(startName,endName-startName).lower();
// skip spaces
- while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
+ while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
if (tagText.at(i)=='=') // option has value
{
c=tagText.at(++i);
// skip spaces
- while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); }
+ while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); }
if (tagText.at(i)=='\'') // option '...'
{
c=tagText.at(++i);
@@ -256,7 +256,7 @@ static void handleHtmlTag()
{
startAttrib=i;
// search for separator or end symbol
- while (i<(int)yyleng && !isspace(c) && c!='>') { c=tagText.at(++i); }
+ while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); }
endAttrib=i;
if (i<(int)yyleng) c=tagText.at(++i);
}
@@ -658,7 +658,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->isEMailAddr=TRUE;
return TK_URL;
}
-<St_Para>"$"{ID}":"[^\n$]+"$" { /* RCS tag */
+<St_Para>"$"{ID}":"[^:\n$][^\n$]*"$" { /* RCS tag */
QCString tagName(yytext+1);
int index=tagName.find(':');
g_token->name = tagName.left(index);
@@ -902,6 +902,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV}
g_token->sectionId = QCString(yytext).stripWhiteSpace();
return RetVal_OK;
}
+<St_PlantUMLOpt>"\n" |
<St_PlantUMLOpt>. {
g_token->sectionId = "";
unput(*yytext);
diff --git a/src/docvisitor.h b/src/docvisitor.h
index d2318c9..0a53595 100644
--- a/src/docvisitor.h
+++ b/src/docvisitor.h
@@ -79,7 +79,6 @@ class DocLinkedWord;
class DocParamSect;
class DocParamList;
class DocInternalRef;
-class DocCopy; // TODO: no longer generated => remove
class DocText;
class DocSimpleSectSep;
class DocHtmlBlockQuote;
@@ -187,8 +186,6 @@ class DocVisitor
virtual void visitPost(DocXRefItem *) = 0;
virtual void visitPre(DocInternalRef *) = 0;
virtual void visitPost(DocInternalRef *) = 0;
- virtual void visitPre(DocCopy *) = 0;
- virtual void visitPost(DocCopy *) = 0;
virtual void visitPre(DocText *) = 0;
virtual void visitPost(DocText *) = 0;
virtual void visitPre(DocHtmlBlockQuote *) = 0;
diff --git a/src/dot.cpp b/src/dot.cpp
index 40a7210..5cdf92c 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -1,13 +1,10 @@
/*****************************************************************************
*
- *
- *
- *
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
+ * Copyright (C) 1997-2019 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
+ * 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.
*
@@ -26,390 +23,47 @@
#include <qwaitcondition.h>
#include <qregexp.h>
+#include "config.h"
#include "dot.h"
-#include "doxygen.h"
-#include "message.h"
+#include "dotrunner.h"
+#include "dotfilepatcher.h"
#include "util.h"
-#include "config.h"
-#include "language.h"
-#include "defargs.h"
-#include "docparser.h"
-#include "debug.h"
-#include "pagedef.h"
#include "portable.h"
-#include "dirdef.h"
-#include "vhdldocgen.h"
+#include "message.h"
#include "ftextstream.h"
-#include "md5.h"
-#include "memberlist.h"
-#include "groupdef.h"
-#include "classlist.h"
-#include "filename.h"
-#include "namespacedef.h"
-#include "memberdef.h"
-#include "membergroup.h"
+#include "doxygen.h"
+#include "language.h"
+#include "index.h"
#define MAP_CMD "cmapx"
-//#define FONTNAME "Helvetica"
-#define FONTNAME getDotFontName()
-#define FONTSIZE getDotFontSize()
-
-//--------------------------------------------------------------------
-
-static const char svgZoomHeader[] =
-"<svg id=\"main\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" onload=\"init(evt)\">\n"
-"<style type=\"text/css\"><![CDATA[\n"
-".edge:hover path { stroke: red; }\n"
-".edge:hover polygon { stroke: red; fill: red; }\n"
-"]]></style>\n"
-"<script type=\"text/javascript\"><![CDATA[\n"
-"var edges = document.getElementsByTagName('g');\n"
-"if (edges && edges.length) {\n"
-" for (var i=0;i<edges.length;i++) {\n"
-" if (edges[i].id.substr(0,4)=='edge') {\n"
-" edges[i].setAttribute('class','edge');\n"
-" }\n"
-" }\n"
-"}\n"
-"]]></script>\n"
-" <defs>\n"
-" <circle id=\"rim\" cx=\"0\" cy=\"0\" r=\"7\"/>\n"
-" <circle id=\"rim2\" cx=\"0\" cy=\"0\" r=\"3.5\"/>\n"
-" <g id=\"zoomPlus\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomplus.mouseover\" end=\"zoomplus.mouseout\"/>\n"
-" </use>\n"
-" <path d=\"M-4,0h8M0,-4v8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
-" </g>\n"
-" <g id=\"zoomMin\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomminus.mouseover\" end=\"zoomminus.mouseout\"/>\n"
-" </use>\n"
-" <path d=\"M-4,0h8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
-" </g>\n"
-" <g id=\"dirArrow\">\n"
-" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
-" </g>\n"
-" <g id=\"resetDef\">\n"
-" <use xlink:href=\"#rim2\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"reset.mouseover\" end=\"reset.mouseout\"/>\n"
-" </use>\n"
-" </g>\n"
-" </defs>\n"
-"\n"
-"<script type=\"text/javascript\">\n"
-;
-
-static const char svgZoomFooter[] =
-// navigation panel
-" <g id=\"navigator\" transform=\"translate(0 0)\" fill=\"#404254\">\n"
-" <rect fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\".5\" x=\"0\" y=\"0\" width=\"60\" height=\"60\"/>\n"
-// zoom in
-" <use id=\"zoomplus\" xlink:href=\"#zoomPlus\" x=\"17\" y=\"9\" onmousedown=\"handleZoom(evt,'in')\"/>\n"
-// zoom out
-" <use id=\"zoomminus\" xlink:href=\"#zoomMin\" x=\"42\" y=\"9\" onmousedown=\"handleZoom(evt,'out')\"/>\n"
-// reset zoom
-" <use id=\"reset\" xlink:href=\"#resetDef\" x=\"30\" y=\"36\" onmousedown=\"handleReset()\"/>\n"
-// arrow up
-" <g id=\"arrowUp\" xlink:href=\"#dirArrow\" transform=\"translate(30 24)\" onmousedown=\"handlePan(0,-1)\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowUp.mouseover\" end=\"arrowUp.mouseout\"/>\n"
-" </use>\n"
-" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
-" </g>\n"
-// arrow right
-" <g id=\"arrowRight\" xlink:href=\"#dirArrow\" transform=\"rotate(90) translate(36 -43)\" onmousedown=\"handlePan(1,0)\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowRight.mouseover\" end=\"arrowRight.mouseout\"/>\n"
-" </use>\n"
-" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
-" </g>\n"
-// arrow down
-" <g id=\"arrowDown\" xlink:href=\"#dirArrow\" transform=\"rotate(180) translate(-30 -48)\" onmousedown=\"handlePan(0,1)\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowDown.mouseover\" end=\"arrowDown.mouseout\"/>\n"
-" </use>\n"
-" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
-" </g>\n"
-// arrow left
-" <g id=\"arrowLeft\" xlink:href=\"#dirArrow\" transform=\"rotate(270) translate(-36 17)\" onmousedown=\"handlePan(-1,0)\">\n"
-" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
-" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowLeft.mouseover\" end=\"arrowLeft.mouseout\"/>\n"
-" </use>\n"
-" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
-" </g>\n"
-" </g>\n"
-// link to original SVG
-" <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n"
-" <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n"
-" <a xlink:href=\"$orgname\" target=\"_base\">\n"
-" <rect id=\"button\" ry=\"5\" rx=\"5\" y=\"6\" x=\"6\" height=\"38\" width=\"38\"\n"
-" fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\"1.0\"/>\n"
-" <path id=\"arrow\"\n"
-" d=\"M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z\"\n"
-" style=\"fill:#404040;\"/>\n"
-" </a>\n"
-" </g>\n"
-" </svg>\n"
-"</svg>\n"
-;
+static int DOT_NUM_THREADS; // will be initialized in initDot
//--------------------------------------------------------------------
-/*! mapping from protection levels to color names */
-static const char *normalEdgeColorMap[] =
-{
- "midnightblue", // Public
- "darkgreen", // Protected
- "firebrick4", // Private
- "darkorchid3", // "use" relation
- "grey75", // Undocumented
- "orange", // template relation
- "orange" // type constraint
-};
-
-static const char *normalArrowStyleMap[] =
-{
- "empty", // Public
- "empty", // Protected
- "empty", // Private
- "open", // "use" relation
- 0, // Undocumented
- 0 // template relation
-};
-
-static const char *normalEdgeStyleMap[] =
-{
- "solid", // inheritance
- "dashed" // usage
-};
-
-static const char *umlEdgeColorMap[] =
-{
- "midnightblue", // Public
- "darkgreen", // Protected
- "firebrick4", // Private
- "grey25", // "use" relation
- "grey75", // Undocumented
- "orange", // template relation
- "orange" // type constraint
-};
-
-static const char *umlArrowStyleMap[] =
-{
- "onormal", // Public
- "onormal", // Protected
- "onormal", // Private
- "odiamond", // "use" relation
- 0, // Undocumented
- 0 // template relation
-};
-
-static const char *umlEdgeStyleMap[] =
-{
- "solid", // inheritance
- "solid" // usage
-};
-
-/** Helper struct holding the properties of a edge in a dot graph. */
-struct EdgeProperties
-{
- const char * const *edgeColorMap;
- const char * const *arrowStyleMap;
- const char * const *edgeStyleMap;
-};
-
-static EdgeProperties normalEdgeProps =
-{
- normalEdgeColorMap, normalArrowStyleMap, normalEdgeStyleMap
-};
-
-static EdgeProperties umlEdgeProps =
+void initDot()
{
- umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap
-};
-
-
-static QCString getDotFontName()
-{
- static QCString dotFontName = Config_getString(DOT_FONTNAME);
- if (dotFontName.isEmpty())
+ DotGraph::DOT_FONTNAME = Config_getString(DOT_FONTNAME);
+ if (DotGraph::DOT_FONTNAME.isEmpty())
{
- //dotFontName="FreeSans.ttf";
- dotFontName="Helvetica";
+ DotGraph::DOT_FONTNAME="Helvetica";
}
- return dotFontName;
-}
-static int getDotFontSize()
-{
- static int dotFontSize = Config_getInt(DOT_FONTSIZE);
- if (dotFontSize<4) dotFontSize=4;
- return dotFontSize;
-}
+ DotGraph::DOT_FONTSIZE = Config_getInt(DOT_FONTSIZE);
+ if (DotGraph::DOT_FONTSIZE<4) DotGraph::DOT_FONTSIZE=4;
-static void writeGraphHeader(FTextStream &t,const QCString &title=QCString())
-{
- static bool interactiveSVG = Config_getBool(INTERACTIVE_SVG);
- t << "digraph ";
- if (title.isEmpty())
- {
- t << "\"Dot Graph\"";
- }
- else
- {
- t << "\"" << convertToXML(title) << "\"";
- }
- t << endl << "{" << endl;
- if (interactiveSVG) // insert a comment to force regeneration when this
- // option is toggled
- {
- t << " // INTERACTIVE_SVG=YES\n";
- }
- t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size repacement
- if (Config_getBool(DOT_TRANSPARENT))
- {
- t << " bgcolor=\"transparent\";" << endl;
- }
- t << " edge [fontname=\"" << FONTNAME << "\","
- "fontsize=\"" << FONTSIZE << "\","
- "labelfontname=\"" << FONTNAME << "\","
- "labelfontsize=\"" << FONTSIZE << "\"];\n";
- t << " node [fontname=\"" << FONTNAME << "\","
- "fontsize=\"" << FONTSIZE << "\",shape=record];\n";
-}
+ DOT_NUM_THREADS = Config_getInt(DOT_NUM_THREADS);
+ if (DOT_NUM_THREADS > 32) DOT_NUM_THREADS = 32;
+ if (DOT_NUM_THREADS <= 0) DOT_NUM_THREADS = QMAX(2,QThread::idealThreadCount()+1);
-static void writeGraphFooter(FTextStream &t)
-{
- t << "}" << endl;
-}
+ // these are copied to be sure to be thread save
+ DotRunner::DOT_CLEANUP = Config_getBool(DOT_CLEANUP);
+ DotRunner::DOT_MULTI_TARGETS = Config_getBool(DOT_MULTI_TARGETS);
+ DotRunner::DOT_EXE.init(Config_getString(DOT_PATH) + "dot");
-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;
- bool setTarget = FALSE;
- 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();
- if (result != "") setTarget = TRUE;
- }
- result+= href+"=\"";
- result+=externalRef(relPath,ref,TRUE);
- result+= url + "\"";
- }
- else // should not happen, but handle properly anyway
- {
- result = href+"=\"" + link + "\"";
- }
- }
- if (!target.isEmpty() && !setTarget)
- {
- result+=" target=\""+target+"\"";
- }
- QCString leftPart = buf.left(indexS);
- QCString rightPart = buf.mid(indexE+1);
- return leftPart + result + rightPart;
- }
- else
- {
- return buf;
- }
+ DotGraph::IMG_EXT = getDotImageExtension();
}
-/*! 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.
- * \param relPath the relative path to the root of the output directory
- * (used in case CREATE_SUBDIRS is enabled).
- * \param urlOnly if FALSE the url field in the map contains an external
- * references followed by a $ and then the URL.
- * \param context the context (file, class, or namespace) in which the
- * map file was found
- * \returns TRUE if successful.
- */
-static bool convertMapFile(FTextStream &t,const char *mapName,
- const QCString relPath, bool urlOnly=FALSE,
- const QCString &context=QCString())
-{
- QFile f(mapName);
- if (!f.open(IO_ReadOnly))
- {
- err("problems opening map file %s for inclusion in the docs!\n"
- "If you installed Graphviz/dot after a previous failing run, \n"
- "try deleting the output directory and rerun doxygen.\n",mapName);
- return FALSE;
- }
- const int maxLineLen=10240;
- while (!f.atEnd()) // foreach line
- {
- QCString buf(maxLineLen);
- int numBytes = f.readLine(buf.rawData(),maxLineLen);
- if (numBytes>0)
- {
- buf.resize(numBytes+1);
-
- if (buf.left(5)=="<area")
- {
- QCString replBuf = replaceRef(buf,relPath,urlOnly,context);
- // strip id="..." from replBuf since the id's are not needed and not unique.
- int indexS = replBuf.find("id=\""), indexE;
- if (indexS>0 && (indexE=replBuf.find('"',indexS+4))!=-1)
- {
- t << replBuf.left(indexS-1) << replBuf.right(replBuf.length() - indexE - 1);
- }
- else
- {
- t << replBuf;
- }
- }
- }
- }
- return TRUE;
-}
static QCString g_dotFontPath;
@@ -448,147 +102,6 @@ static void unsetDotFontPath()
g_dotFontPath="";
}
-static bool resetPDFSize(const int width,const int height, const char *base)
-{
- QString tmpName = QString::fromUtf8(QCString(base)+".tmp");
- QString patchFile = QString::fromUtf8(QCString(base)+".dot");
- if (!QDir::current().rename(patchFile,tmpName))
- {
- err("Failed to rename file %s to %s!\n",patchFile.data(),tmpName.data());
- return FALSE;
- }
- QFile fi(tmpName);
- QFile fo(patchFile);
- if (!fi.open(IO_ReadOnly))
- {
- err("problem opening file %s for patching!\n",tmpName.data());
- QDir::current().rename(tmpName,patchFile);
- return FALSE;
- }
- if (!fo.open(IO_WriteOnly))
- {
- err("problem opening file %s for patching!\n",patchFile.data());
- QDir::current().rename(tmpName,patchFile);
- fi.close();
- return FALSE;
- }
- FTextStream t(&fo);
- const int maxLineLen=100*1024;
- while (!fi.atEnd()) // foreach line
- {
- QCString line(maxLineLen);
- int numBytes = fi.readLine(line.rawData(),maxLineLen);
- if (numBytes<=0)
- {
- break;
- }
- line.resize(numBytes+1);
- if (line.find("LATEX_PDF_SIZE") != -1)
- {
- double scale = (width > height ? width : height)/double(MAX_LATEX_GRAPH_INCH);
- t << " size=\""<<width/scale << "," <<height/scale <<"\";\n";
- }
- else
- t << line;
- }
- fi.close();
- fo.close();
- // remove temporary file
- QDir::current().remove(tmpName);
- return TRUE;
-}
-static bool readBoundingBox(const char *fileName,int *width,int *height,bool isEps)
-{
- QCString bb = isEps ? QCString("%%PageBoundingBox:") : QCString("/MediaBox [");
- QFile f(fileName);
- if (!f.open(IO_ReadOnly|IO_Raw))
- {
- //printf("readBoundingBox: could not open %s\n",fileName);
- return FALSE;
- }
- const int maxLineLen=1024;
- char buf[maxLineLen];
- while (!f.atEnd())
- {
- int numBytes = f.readLine(buf,maxLineLen-1); // read line
- if (numBytes>0)
- {
- buf[numBytes]='\0';
- const char *p = strstr(buf,bb);
- if (p) // found PageBoundingBox or /MediaBox string
- {
- int x,y;
- if (sscanf(p+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4)
- {
- //printf("readBoundingBox sscanf fail\n");
- return FALSE;
- }
- return TRUE;
- }
- }
- else // read error!
- {
- //printf("Read error %d!\n",numBytes);
- return FALSE;
- }
- }
- err("Failed to extract bounding box from generated diagram file %s\n",fileName);
- return FALSE;
-}
-
-static bool writeVecGfxFigure(FTextStream &out,const QCString &baseName,
- const QCString &figureName)
-{
- int width=400,height=550;
- static bool usePdfLatex = Config_getBool(USE_PDFLATEX);
- if (usePdfLatex)
- {
- if (!readBoundingBox(figureName+".pdf",&width,&height,FALSE))
- {
- //printf("writeVecGfxFigure()=0\n");
- return FALSE;
- }
- }
- else
- {
- if (!readBoundingBox(figureName+".eps",&width,&height,TRUE))
- {
- //printf("writeVecGfxFigure()=0\n");
- return FALSE;
- }
- }
- //printf("Got PDF/EPS size %d,%d\n",width,height);
- int maxWidth = 350; /* approx. page width in points, excl. margins */
- int maxHeight = 550; /* approx. page height in points, excl. margins */
- out << "\\nopagebreak\n"
- "\\begin{figure}[H]\n"
- "\\begin{center}\n"
- "\\leavevmode\n";
- if (width>maxWidth || height>maxHeight) // figure too big for page
- {
- // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0
- if (width*maxHeight>height*maxWidth)
- {
- out << "\\includegraphics[width=" << maxWidth << "pt]";
- }
- else
- {
- out << "\\includegraphics[height=" << maxHeight << "pt]";
- }
- }
- else
- {
- out << "\\includegraphics[width=" << width << "pt]";
- }
-
- out << "{" << baseName << "}\n"
- "\\end{center}\n"
- "\\end{figure}\n";
-
- //printf("writeVecGfxFigure()=1\n");
- return TRUE;
-}
-
// extract size from a dot generated SVG file
static bool readSVGSize(const QCString &fileName,int *width,int *height)
{
@@ -636,8 +149,8 @@ static void writeSVGNotSupported(FTextStream &out)
// 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)
+bool writeSVGFigureLink(FTextStream &out,const QCString &relPath,
+ const QCString &baseName,const QCString &absImgName)
{
int width=600,height=600;
if (!readSVGSize(absImgName,&width,&height))
@@ -678,593 +191,6 @@ static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath,
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 char *imgExt, const char *imgName)
-{
- if (qstrcmp(imgExt,"png")==0)
- {
- FILE *f = portable_fopen(imgName,"rb");
- if (f)
- {
- char data[4];
- if (fread(data,1,4,f)==4)
- {
- if (!(data[1]=='P' && data[2]=='N' && data[3]=='G'))
- {
- err("Image `%s' produced by dot is not a valid PNG!\n"
- "You should either select a different format "
- "(DOT_IMAGE_FORMAT in the config file) or install a more "
- "recent version of graphviz (1.7+)\n",imgName
- );
- }
- }
- else
- {
- err("Could not read image `%s' generated by dot!\n",imgName);
- }
- fclose(f);
- }
- else
- {
- err("Could not open image `%s' generated by dot!\n",imgName);
- }
- }
-}
-
-static bool insertMapFile(FTextStream &out,const QCString &mapFile,
- const QCString &relPath,const QCString &mapLabel)
-{
- QFileInfo fi(mapFile);
- if (fi.exists() && fi.size()>0) // reuse existing map file
- {
- QGString tmpstr;
- FTextStream tmpout(&tmpstr);
- convertMapFile(tmpout,mapFile,relPath,TRUE);
- if (!tmpstr.isEmpty())
- {
- out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl;
- out << tmpstr;
- out << "</map>" << endl;
- }
- return TRUE;
- }
- return FALSE; // no map file yet, need to generate it
-}
-
-static void removeDotGraph(const QCString &dotName)
-{
- static bool dotCleanUp = Config_getBool(DOT_CLEANUP);
- if (dotCleanUp)
- {
- QDir d;
- d.remove(dotName);
- }
-}
-
-
-
-/*! Checks if a file "baseName".md5 exists. If so the contents
- * are compared with \a md5. If equal FALSE is returned. If the .md5
- * file does not exist or its contents are not equal to \a md5,
- * a new .md5 is generated with the \a md5 string as contents.
- */
-static bool checkAndUpdateMd5Signature(const QCString &baseName,
- const QCString &md5)
-{
- QFile f(baseName+".md5");
- if (f.open(IO_ReadOnly))
- {
- // read checksum
- QCString md5stored(33);
- int bytesRead=f.readBlock(md5stored.rawData(),32);
- md5stored[32]='\0';
- // compare checksum
- if (bytesRead==32 && md5==md5stored)
- {
- // bail out if equal
- return FALSE;
- }
- }
- f.close();
- // create checksum file
- if (f.open(IO_WriteOnly))
- {
- f.writeBlock(md5.data(),32);
- f.close();
- }
- return TRUE;
-}
-
-static bool checkDeliverables(const QCString &file1,
- const QCString &file2=QCString())
-{
- bool file1Ok = TRUE;
- bool file2Ok = TRUE;
- if (!file1.isEmpty())
- {
- QFileInfo fi(file1);
- file1Ok = (fi.exists() && fi.size()>0);
- }
- if (!file2.isEmpty())
- {
- QFileInfo fi(file2);
- file2Ok = (fi.exists() && fi.size()>0);
- }
- return file1Ok && file2Ok;
-}
-
-//--------------------------------------------------------------------
-
-inline int DotNode::findParent( DotNode *n )
-{
- if ( !m_parents ) return -1;
- return m_parents->find(n);
-}
-
-//--------------------------------------------------------------------
-
-int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const
-{
- return qstricmp(n1->m_label,n2->m_label);
-}
-
-//--------------------------------------------------------------------
-
-DotRunner::DotRunner(const QCString &file,const QCString &path,
- bool checkResult,const QCString &imageName)
- : m_dotExe(Config_getString(DOT_PATH)+"dot"),
- m_file(file), m_path(path),
- m_checkResult(checkResult), m_imageName(imageName),
- m_imgExt(getDotImageExtension())
-{
- static bool dotCleanUp = Config_getBool(DOT_CLEANUP);
- static bool dotMultiTargets = Config_getBool(DOT_MULTI_TARGETS);
- m_cleanUp = dotCleanUp;
- m_multiTargets = dotMultiTargets;
- m_jobs.setAutoDelete(TRUE);
-}
-
-void DotRunner::addJob(const char *format,const char *output, const char *base)
-{
- QCString args = QCString("-T")+format+" -o \""+output+"\"";
- m_jobs.append(new DotConstString(args, base));
-}
-
-void DotRunner::addPostProcessing(const char *cmd,const char *args)
-{
- m_postCmd.set(cmd);
- m_postArgs.set(args);
-}
-
-bool DotRunner::run()
-{
- int exitCode=0;
- int width=0,height=0;
-
- QCString dotArgs;
- QListIterator<DotConstString> li(m_jobs);
- DotConstString *s;
- if (m_multiTargets)
- {
- dotArgs=QCString("\"")+m_file.data()+"\"";
- for (li.toFirst();(s=li.current());++li)
- {
- dotArgs+=' ';
- dotArgs+=s->data();
- }
- if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error;
- dotArgs=QCString("\"")+m_file.data()+"\"";
- bool redo = FALSE;
- for (li.toFirst();(s=li.current());++li)
- {
- if (s->pdfData())
- {
- if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error;
- if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE))
- {
- if (!resetPDFSize(width,height,s->pdfData())) goto error;
- dotArgs+=' ';
- dotArgs+=s->data();
- redo = TRUE;
- }
- }
- }
- if (redo)
- {
- if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error;
- }
- }
- else
- {
- for (li.toFirst();(s=li.current());++li)
- {
- dotArgs=QCString("\"")+m_file.data()+"\" "+s->data();
- if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error;
- if (s->pdfData())
- {
- if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error;
- if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE))
- {
- if (!resetPDFSize(width,height,s->pdfData())) goto error;
- if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error;
- }
- }
- }
- }
- if (!m_postCmd.isEmpty() && portable_system(m_postCmd.data(),m_postArgs.data())!=0)
- {
- err("Problems running '%s' as a post-processing step for dot output\n",m_postCmd.data());
- return FALSE;
- }
- if (m_checkResult)
- {
- checkDotResult(m_imgExt.data(),m_imageName.data());
- }
- if (m_cleanUp)
- {
- //printf("removing dot file %s\n",m_file.data());
- //QDir(path).remove(file);
- m_cleanupItem.file.set(m_file.data());
- m_cleanupItem.path.set(m_path.data());
- }
- return TRUE;
-error:
- err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n",
- exitCode,m_dotExe.data(),dotArgs.data());
- return FALSE;
-}
-
-//--------------------------------------------------------------------
-
-DotFilePatcher::DotFilePatcher(const char *patchFile)
- : m_patchFile(patchFile)
-{
- m_maps.setAutoDelete(TRUE);
-}
-
-QCString DotFilePatcher::file() const
-{
- return m_patchFile;
-}
-
-int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath,
- bool urlOnly,const QCString &context,const QCString &label)
-{
- int id = m_maps.count();
- Map *map = new Map;
- map->mapFile = mapFile;
- map->relPath = relPath;
- map->urlOnly = urlOnly;
- map->context = context;
- map->label = label;
- map->zoomable = FALSE;
- map->graphId = -1;
- m_maps.append(map);
- return id;
-}
-
-int DotFilePatcher::addFigure(const QCString &baseName,
- const QCString &figureName,bool heightCheck)
-{
- int id = m_maps.count();
- Map *map = new Map;
- map->mapFile = figureName;
- map->urlOnly = heightCheck;
- map->label = baseName;
- map->zoomable = FALSE;
- map->graphId = -1;
- m_maps.append(map);
- return id;
-}
-
-int DotFilePatcher::addSVGConversion(const QCString &relPath,bool urlOnly,
- const QCString &context,bool zoomable,
- int graphId)
-{
- int id = m_maps.count();
- Map *map = new Map;
- map->relPath = relPath;
- map->urlOnly = urlOnly;
- map->context = context;
- map->zoomable = zoomable;
- map->graphId = graphId;
- 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;
- map->zoomable = FALSE;
- map->graphId = -1;
- m_maps.append(map);
- return id;
-}
-
-bool DotFilePatcher::run()
-{
- //printf("DotFilePatcher::run(): %s\n",m_patchFile.data());
- static bool interactiveSVG = Config_getBool(INTERACTIVE_SVG);
- bool isSVGFile = m_patchFile.right(4)==".svg";
- int graphId = -1;
- QCString relPath;
- if (isSVGFile)
- {
- Map *map = m_maps.at(0); // there is only one 'map' for a SVG file
- interactiveSVG = interactiveSVG && map->zoomable;
- graphId = map->graphId;
- relPath = map->relPath;
- //printf("DotFilePatcher::addSVGConversion: file=%s zoomable=%d\n",
- // m_patchFile.data(),map->zoomable);
- }
- QString tmpName = QString::fromUtf8(m_patchFile+".tmp");
- QString patchFile = QString::fromUtf8(m_patchFile);
- if (!QDir::current().rename(patchFile,tmpName))
- {
- err("Failed to rename file %s to %s!\n",m_patchFile.data(),tmpName.data());
- return FALSE;
- }
- QFile fi(tmpName);
- QFile fo(patchFile);
- if (!fi.open(IO_ReadOnly))
- {
- err("problem opening file %s for patching!\n",tmpName.data());
- QDir::current().rename(tmpName,patchFile);
- return FALSE;
- }
- if (!fo.open(IO_WriteOnly))
- {
- err("problem opening file %s for patching!\n",m_patchFile.data());
- QDir::current().rename(tmpName,patchFile);
- return FALSE;
- }
- FTextStream t(&fo);
- const int maxLineLen=100*1024;
- int lineNr=1;
- int width,height;
- bool insideHeader=FALSE;
- bool replacedHeader=FALSE;
- bool foundSize=FALSE;
- while (!fi.atEnd()) // foreach line
- {
- QCString line(maxLineLen);
- int numBytes = fi.readLine(line.rawData(),maxLineLen);
- if (numBytes<=0)
- {
- break;
- }
- line.resize(numBytes+1);
-
- //printf("line=[%s]\n",line.stripWhiteSpace().data());
- int i;
- ASSERT(numBytes<maxLineLen);
- if (isSVGFile)
- {
- if (interactiveSVG)
- {
- if (line.find("<svg")!=-1 && !replacedHeader)
- {
- int count;
- count = sscanf(line.data(),"<svg width=\"%dpt\" height=\"%dpt\"",&width,&height);
- //printf("width=%d height=%d\n",width,height);
- foundSize = count==2 && (width>500 || height>450);
- if (foundSize) insideHeader=TRUE;
- }
- else if (insideHeader && !replacedHeader && line.find("<title>")!=-1)
- {
- if (foundSize)
- {
- // insert special replacement header for interactive SVGs
- t << "<!--zoomable " << height << " -->\n";
- t << svgZoomHeader;
- t << "var viewWidth = " << width << ";\n";
- t << "var viewHeight = " << height << ";\n";
- if (graphId>=0)
- {
- t << "var sectionId = 'dynsection-" << graphId << "';\n";
- }
- t << "</script>\n";
- t << "<script xlink:href=\"" << relPath << "svgpan.js\"/>\n";
- t << "<svg id=\"graph\" class=\"graph\">\n";
- t << "<g id=\"viewport\">\n";
- }
- insideHeader=FALSE;
- replacedHeader=TRUE;
- }
- }
- if (!insideHeader || !foundSize) // copy SVG and replace refs,
- // unless we are inside the header of the SVG.
- // Then we replace it with another header.
- {
- 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);
- //printf("DotFilePatcher::writeSVGFigure: file=%s zoomable=%d\n",
- // m_patchFile.data(),map->zoomable);
- 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;
- t << line.left(i);
- int n = sscanf(line.data()+i,"<!-- MAP %d",&mapId);
- if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
- {
- QGString result;
- FTextStream tt(&result);
- Map *map = m_maps.at(mapId);
- //printf("patching MAP %d in file %s with contents of %s\n",
- // mapId,m_patchFile.data(),map->mapFile.data());
- convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context);
- if (!result.isEmpty())
- {
- t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl;
- t << result;
- t << "</map>" << endl;
- }
- }
- else // error invalid map id!
- {
- err("Found invalid MAP id in file %s!\n",m_patchFile.data());
- t << line.mid(i);
- }
- }
- else if ((i=line.find("% FIG"))!=-1)
- {
- int mapId=-1;
- int n = sscanf(line.data()+i+2,"FIG %d",&mapId);
- //printf("line='%s' n=%d\n",line.data()+i,n);
- if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
- {
- Map *map = m_maps.at(mapId);
- //printf("patching FIG %d in file %s with contents of %s\n",
- // mapId,m_patchFile.data(),map->mapFile.data());
- if (!writeVecGfxFigure(t,map->label,map->mapFile))
- {
- err("problem writing FIG %d figure!\n",mapId);
- return FALSE;
- }
- }
- else // error invalid map id!
- {
- err("Found invalid bounding FIG %d in file %s!\n",mapId,m_patchFile.data());
- t << line;
- }
- }
- else
- {
- t << line;
- }
- lineNr++;
- }
- fi.close();
- if (isSVGFile && interactiveSVG && replacedHeader)
- {
- QCString orgName=m_patchFile.left(m_patchFile.length()-4)+"_org.svg";
- t << substitute(svgZoomFooter,"$orgname",stripPath(orgName));
- fo.close();
- // keep original SVG file so we can refer to it, we do need to replace
- // dummy link by real ones
- QFile fi(tmpName);
- QFile fo(orgName);
- if (!fi.open(IO_ReadOnly))
- {
- err("problem opening file %s for reading!\n",tmpName.data());
- return FALSE;
- }
- if (!fo.open(IO_WriteOnly))
- {
- err("problem opening file %s for writing!\n",orgName.data());
- return FALSE;
- }
- FTextStream t(&fo);
- while (!fi.atEnd()) // foreach line
- {
- QCString line(maxLineLen);
- int numBytes = fi.readLine(line.rawData(),maxLineLen);
- if (numBytes<=0)
- {
- break;
- }
- line.resize(numBytes+1);
- 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");
- }
- fi.close();
- fo.close();
- }
- // remove temporary file
- QDir::current().remove(tmpName);
- return TRUE;
-}
-
-//--------------------------------------------------------------------
-
-void DotRunnerQueue::enqueue(DotRunner *runner)
-{
- QMutexLocker locker(&m_mutex);
- m_queue.enqueue(runner);
- m_bufferNotEmpty.wakeAll();
-}
-
-DotRunner *DotRunnerQueue::dequeue()
-{
- QMutexLocker locker(&m_mutex);
- while (m_queue.isEmpty())
- {
- // wait until something is added to the queue
- m_bufferNotEmpty.wait(&m_mutex);
- }
- DotRunner *result = m_queue.dequeue();
- return result;
-}
-
-uint DotRunnerQueue::count() const
-{
- QMutexLocker locker(&m_mutex);
- return m_queue.count();
-}
-
-//--------------------------------------------------------------------
-
-DotWorkerThread::DotWorkerThread(DotRunnerQueue *queue)
- : m_queue(queue)
-{
- m_cleanupItems.setAutoDelete(TRUE);
-}
-
-void DotWorkerThread::run()
-{
- DotRunner *runner;
- while ((runner=m_queue->dequeue()))
- {
- runner->run();
- const DotRunner::CleanupItem &cleanup = runner->cleanup();
- if (!cleanup.file.isEmpty())
- {
- m_cleanupItems.append(new DotRunner::CleanupItem(cleanup));
- }
- }
-}
-
-void DotWorkerThread::cleanup()
-{
- QListIterator<DotRunner::CleanupItem> it(m_cleanupItems);
- DotRunner::CleanupItem *ci;
- for (;(ci=it.current());++it)
- {
- QDir(ci->path.data()).remove(ci->file.data());
- }
-}
-
//--------------------------------------------------------------------
DotManager *DotManager::m_theInstance = 0;
@@ -1280,15 +206,13 @@ DotManager *DotManager::instance()
DotManager::DotManager() : m_dotMaps(1009)
{
- m_dotRuns.setAutoDelete(TRUE);
+ m_runners.setAutoDelete(TRUE);
m_dotMaps.setAutoDelete(TRUE);
m_queue = new DotRunnerQueue;
int i;
- int numThreads = QMIN(32,Config_getInt(DOT_NUM_THREADS));
- if (numThreads!=1)
+ if (DOT_NUM_THREADS!=1)
{
- if (numThreads==0) numThreads = QMAX(2,QThread::idealThreadCount()+1);
- for (i=0;i<numThreads;i++)
+ for (i=0;i<DOT_NUM_THREADS;i++)
{
DotWorkerThread *thread = new DotWorkerThread(m_queue);
thread->start();
@@ -1310,11 +234,26 @@ DotManager::~DotManager()
delete m_queue;
}
-void DotManager::addRun(DotRunner *run)
+DotRunner* DotManager::createRunner(const QCString& absDotName, const QCString& md5Hash)
{
- m_dotRuns.append(run);
+ DotRunner * run = m_runners.find(absDotName);
+ if (run == 0)
+ {
+ run = new DotRunner(absDotName, md5Hash);
+ m_runners.insert(absDotName, run);
+ }
+ else
+ {
+ // we have a match
+ if (md5Hash != QCString(run->getMd5Hash().data()))
+ {
+ err("md5 hash does not match for two different runs of %s !\n", absDotName.data());
+ }
+ }
+ return run;
}
+
int DotManager::addMap(const QCString &file,const QCString &mapFile,
const QCString &relPath,bool urlOnly,const QCString &context,
const QCString &label)
@@ -1367,7 +306,7 @@ int DotManager::addSVGObject(const QCString &file,const QCString &baseName,
bool DotManager::run()
{
- uint numDotRuns = m_dotRuns.count();
+ uint numDotRuns = m_runners.count();
uint numDotMaps = m_dotMaps.count();
if (numDotRuns+numDotMaps>1)
{
@@ -1381,7 +320,7 @@ bool DotManager::run()
}
}
int i=1;
- QListIterator<DotRunner> li(m_dotRuns);
+ QDictIterator<DotRunner> li(m_runners);
bool setPath=FALSE;
if (Config_getBool(GENERATE_HTML))
@@ -1449,11 +388,6 @@ bool DotManager::run()
{
m_workers.at(i)->wait();
}
- // clean up dot files from main thread
- for (i=0;i<(int)m_workers.count();i++)
- {
- m_workers.at(i)->cleanup();
- }
}
portable_sysTimerStop();
if (setPath)
@@ -1492,2756 +426,59 @@ bool DotManager::run()
//--------------------------------------------------------------------
-
-/*! helper function that deletes all nodes in a connected graph, given
- * one of the graph's nodes
- */
-static void deleteNodes(DotNode *node,SDict<DotNode> *skipNodes=0)
-{
- //printf("deleteNodes skipNodes=%p\n",skipNodes);
- static DotNodeList deletedNodes;
- deletedNodes.setAutoDelete(TRUE);
- node->deleteNode(deletedNodes,skipNodes); // collect nodes to be deleted.
- deletedNodes.clear(); // actually remove the nodes.
-}
-
-DotNode::DotNode(int n,const char *lab,const char *tip, const char *url,
- bool isRoot,ClassDef *cd)
- : m_subgraphId(-1)
- , m_number(n)
- , m_label(lab)
- , m_tooltip(tip)
- , m_url(url)
- , m_parents(0)
- , m_children(0)
- , m_edgeInfo(0)
- , m_deleted(FALSE)
- , m_written(FALSE)
- , m_hasDoc(FALSE)
- , m_isRoot(isRoot)
- , m_classDef(cd)
- , m_visible(FALSE)
- , m_truncated(Unknown)
- , m_distance(1000)
- , m_renumbered(false)
-{
-}
-
-DotNode::~DotNode()
-{
- delete m_children;
- delete m_parents;
- delete m_edgeInfo;
-}
-
-void DotNode::addChild(DotNode *n,
- int edgeColor,
- int edgeStyle,
- const char *edgeLab,
- const char *edgeURL,
- int edgeLabCol
- )
-{
- if (m_children==0)
- {
- m_children = new QList<DotNode>;
- m_edgeInfo = new QList<EdgeInfo>;
- m_edgeInfo->setAutoDelete(TRUE);
- }
- m_children->append(n);
- EdgeInfo *ei = new EdgeInfo;
- ei->m_color = edgeColor;
- ei->m_style = edgeStyle;
- ei->m_label = edgeLab;
- ei->m_url = edgeURL;
- if (edgeLabCol==-1)
- ei->m_labColor=edgeColor;
- else
- ei->m_labColor=edgeLabCol;
- m_edgeInfo->append(ei);
-}
-
-void DotNode::addParent(DotNode *n)
-{
- if (m_parents==0)
- {
- m_parents = new QList<DotNode>;
- }
- m_parents->append(n);
-}
-
-void DotNode::removeChild(DotNode *n)
-{
- if (m_children) m_children->remove(n);
-}
-
-void DotNode::removeParent(DotNode *n)
-{
- if (m_parents) m_parents->remove(n);
-}
-
-void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes)
-{
- if (m_deleted) return; // avoid recursive loops in case the graph has cycles
- m_deleted=TRUE;
- if (m_parents!=0) // delete all parent nodes of this node
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- //pn->removeChild(this);
- pn->deleteNode(deletedList,skipNodes);
- }
- }
- if (m_children!=0) // delete all child nodes of this node
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- //cn->removeParent(this);
- cn->deleteNode(deletedList,skipNodes);
- }
- }
- // add this node to the list of deleted nodes.
- //printf("skipNodes=%p find(%p)=%p\n",skipNodes,this,skipNodes ? skipNodes->find((int)this) : 0);
- if (skipNodes==0 || skipNodes->find((char*)this)==0)
- {
- //printf("deleting\n");
- deletedList.append(this);
- }
-}
-
-void DotNode::setDistance(int distance)
-{
- if (distance<m_distance) m_distance = distance;
-}
-
-static QCString convertLabel(const QCString &l)
-{
- QString bBefore("\\_/<({[: =-+@%#~?$"); // break before character set
- QString bAfter(">]),:;|"); // break after character set
- QString p(l);
- if (p.isEmpty()) return QCString();
- QString result;
- QChar c,pc=0;
- uint idx = 0;
- int len=p.length();
- int charsLeft=len;
- int sinceLast=0;
- int foldLen=17; // ideal text length
- while (idx < p.length())
- {
- c = p[idx++];
- QString replacement;
- switch(c)
- {
- case '\\': replacement="\\\\"; break;
- case '\n': replacement="\\n"; break;
- case '<': replacement="\\<"; break;
- case '>': replacement="\\>"; break;
- case '|': replacement="\\|"; break;
- case '{': replacement="\\{"; break;
- case '}': replacement="\\}"; break;
- case '"': replacement="\\\""; break;
- default: replacement=c; break;
- }
- // Some heuristics to insert newlines to prevent too long
- // boxes and at the same time prevent ugly breaks
- if (c=='\n')
- {
- result+=replacement;
- foldLen = (3*foldLen+sinceLast+2)/4;
- sinceLast=1;
- }
- else if ((pc!=':' || c!=':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.contains(c))
- {
- result+="\\l";
- result+=replacement;
- foldLen = (foldLen+sinceLast+1)/2;
- sinceLast=1;
- }
- else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 &&
- !isupper(c) && p[idx].category()==QChar::Letter_Uppercase)
- {
- result+=replacement;
- result+="\\l";
- foldLen = (foldLen+sinceLast+1)/2;
- sinceLast=0;
- }
- else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.contains(c) && (c!=':' || p[idx]!=':'))
- {
- result+=replacement;
- result+="\\l";
- foldLen = (foldLen+sinceLast+1)/2;
- sinceLast=0;
- }
- else
- {
- result+=replacement;
- sinceLast++;
- }
- charsLeft--;
- pc=c;
- }
- return result.utf8();
-}
-
-static QCString escapeTooltip(const QCString &tooltip)
-{
- QCString result;
- const char *p=tooltip.data();
- if (p==0) return result;
- char c;
- while ((c=*p++))
- {
- switch(c)
- {
- case '"': result+="\\\""; break;
- default: result+=c; break;
- }
- }
- return result;
-}
-
-static void writeBoxMemberList(FTextStream &t,
- char prot,MemberList *ml,ClassDef *scope,
- bool isStatic=FALSE,const QDict<void> *skipNames=0)
-{
- (void)isStatic;
- if (ml)
- {
- MemberListIterator mlia(*ml);
- MemberDef *mma;
- int totalCount=0;
- for (mlia.toFirst();(mma = mlia.current());++mlia)
- {
- if (mma->getClassDef()==scope &&
- (skipNames==0 || skipNames->find(mma->name())==0))
- {
- totalCount++;
- }
- }
-
- int count=0;
- for (mlia.toFirst();(mma = mlia.current());++mlia)
- {
- if (mma->getClassDef() == scope &&
- (skipNames==0 || skipNames->find(mma->name())==0))
- {
- static int limit = Config_getInt(UML_LIMIT_NUM_FIELDS);
- if (limit>0 && (totalCount>limit*3/2 && count>=limit))
- {
- t << theTranslator->trAndMore(QCString().sprintf("%d",totalCount-count)) << "\\l";
- break;
- }
- else
- {
- t << prot << " ";
- t << convertLabel(mma->name());
- if (!mma->isObjCMethod() &&
- (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()";
- t << "\\l";
- count++;
- }
- }
- }
- // write member groups within the memberlist
- MemberGroupList *mgl = ml->getMemberGroupList();
- if (mgl)
- {
- MemberGroupListIterator mgli(*mgl);
- MemberGroup *mg;
- for (mgli.toFirst();(mg=mgli.current());++mgli)
- {
- if (mg->members())
- {
- writeBoxMemberList(t,prot,mg->members(),scope,isStatic,skipNames);
- }
- }
- }
- }
-}
-
-static QCString stripProtectionPrefix(const QCString &s)
-{
- if (!s.isEmpty() && (s[0]=='-' || s[0]=='+' || s[0]=='~' || s[0]=='#'))
- {
- return s.mid(1);
- }
- else
- {
- return s;
- }
-}
-
-void DotNode::writeBox(FTextStream &t,
- GraphType gt,
- GraphOutputFormat /*format*/,
- bool hasNonReachableChildren
- )
-{
- const char *labCol =
- m_url.isEmpty() ? "grey75" : // non link
- (
- (hasNonReachableChildren) ? "red" : "black"
- );
- t << " Node" << m_number << " [label=\"";
- static bool umlLook = Config_getBool(UML_LOOK);
-
- if (m_classDef && umlLook && (gt==Inheritance || gt==Collaboration))
- {
- // add names shown as relations to a dictionary, so we don't show
- // them as attributes as well
- QDict<void> arrowNames(17);
- if (m_edgeInfo)
- {
- // for each edge
- QListIterator<EdgeInfo> li(*m_edgeInfo);
- EdgeInfo *ei;
- for (li.toFirst();(ei=li.current());++li)
- {
- if (!ei->m_label.isEmpty()) // labels joined by \n
- {
- int li=ei->m_label.find('\n');
- int p=0;
- QCString lab;
- while ((li=ei->m_label.find('\n',p))!=-1)
- {
- lab = stripProtectionPrefix(ei->m_label.mid(p,li-p));
- arrowNames.insert(lab,(void*)0x8);
- p=li+1;
- }
- lab = stripProtectionPrefix(ei->m_label.right(ei->m_label.length()-p));
- arrowNames.insert(lab,(void*)0x8);
- }
- }
- }
-
- //printf("DotNode::writeBox for %s\n",m_classDef->name().data());
- static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
- t << "{" << convertLabel(m_label);
- t << "\\n|";
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames);
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames);
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames);
- writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames);
- writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames);
- writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames);
- writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames);
- if (extractPrivate)
- {
- writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames);
- writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames);
- }
- t << "|";
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef);
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE);
- writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef);
- writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef);
- writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE);
- writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef);
- writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE);
- writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef);
- if (extractPrivate)
- {
- writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef);
- writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE);
- writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef);
- }
- if (m_classDef->getLanguage()!=SrcLangExt_Fortran &&
- m_classDef->getMemberGroupSDict())
- {
- MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict());
- MemberGroup *mg;
- for (mgdi.toFirst();(mg=mgdi.current());++mgdi)
- {
- if (mg->members())
- {
- writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames);
- }
- }
- }
- t << "}";
- }
- else // standard look
- {
- t << convertLabel(m_label);
- }
- t << "\",height=0.2,width=0.4";
- if (m_isRoot)
- {
- t << ",color=\"black\", fillcolor=\"grey75\", style=\"filled\", fontcolor=\"black\"";
- }
- else
- {
- static bool dotTransparent = Config_getBool(DOT_TRANSPARENT);
- if (!dotTransparent)
- {
- t << ",color=\"" << labCol << "\", fillcolor=\"";
- t << "white";
- t << "\", style=\"filled\"";
- }
- else
- {
- t << ",color=\"" << labCol << "\"";
- }
- if (!m_url.isEmpty())
- {
- int anchorPos = m_url.findRev('#');
- if (anchorPos==-1)
- {
- t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\"";
- }
- else
- {
- t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension
- << m_url.right(m_url.length()-anchorPos) << "\"";
- }
- }
- }
- if (!m_tooltip.isEmpty())
- {
- t << ",tooltip=\"" << escapeTooltip(m_tooltip) << "\"";
- }
- else
- {
- t << ",tooltip=\" \""; // space in tooltip is required otherwise still something like 'Node0' is used
- }
- t << "];" << endl;
-}
-
-void DotNode::writeArrow(FTextStream &t,
- GraphType gt,
- GraphOutputFormat format,
- DotNode *cn,
- EdgeInfo *ei,
- bool topDown,
- bool pointBack
- )
-{
- t << " Node";
- if (topDown)
- t << cn->number();
- else
- t << m_number;
- t << " -> Node";
- if (topDown)
- t << m_number;
- else
- t << cn->number();
- t << " [";
-
- static bool umlLook = Config_getBool(UML_LOOK);
- const EdgeProperties *eProps = umlLook ? &umlEdgeProps : &normalEdgeProps;
- QCString aStyle = eProps->arrowStyleMap[ei->m_color];
- bool umlUseArrow = aStyle=="odiamond";
-
- if (pointBack && !umlUseArrow) t << "dir=\"back\",";
- t << "color=\"" << eProps->edgeColorMap[ei->m_color]
- << "\",fontsize=\"" << FONTSIZE << "\",";
- t << "style=\"" << eProps->edgeStyleMap[ei->m_style] << "\"";
- if (!ei->m_label.isEmpty())
- {
- t << ",label=\" " << convertLabel(ei->m_label) << "\" ";
- }
- if (umlLook &&
- eProps->arrowStyleMap[ei->m_color] &&
- (gt==Inheritance || gt==Collaboration)
- )
- {
- bool rev = pointBack;
- if (umlUseArrow) rev=!rev; // UML use relates has arrow on the start side
- if (rev)
- t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->m_color] << "\"";
- else
- t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->m_color] << "\"";
- }
-
- if (format==GOF_BITMAP) t << ",fontname=\"" << FONTNAME << "\"";
- t << "];" << endl;
-}
-
-void DotNode::write(FTextStream &t,
- GraphType gt,
- GraphOutputFormat format,
- bool topDown,
- bool toChildren,
- bool backArrows
- )
-{
- //printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible);
- if (m_written) return; // node already written to the output
- if (!m_visible) return; // node is not visible
- writeBox(t,gt,format,m_truncated==Truncated);
- m_written=TRUE;
- QList<DotNode> *nl = toChildren ? m_children : m_parents;
- if (nl)
- {
- if (toChildren)
- {
- QListIterator<DotNode> dnli1(*nl);
- QListIterator<EdgeInfo> dnli2(*m_edgeInfo);
- DotNode *cn;
- for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
- {
- if (cn->isVisible())
- {
- //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",cn->label().data());
- writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows);
- }
- cn->write(t,gt,format,topDown,toChildren,backArrows);
- }
- }
- else // render parents
- {
- QListIterator<DotNode> dnli(*nl);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (pn->isVisible())
- {
- //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",pn->label().data());
- writeArrow(t,
- gt,
- format,
- pn,
- pn->m_edgeInfo->at(pn->m_children->findRef(this)),
- FALSE,
- backArrows
- );
- }
- pn->write(t,gt,format,TRUE,FALSE,backArrows);
- }
- }
- }
- //printf("end DotNode::write(%d) name=%s\n",distance,m_label.data());
-}
-
-void DotNode::writeXML(FTextStream &t,bool isClassGraph)
-{
- t << " <node id=\"" << m_number << "\">" << endl;
- t << " <label>" << convertToXML(m_label) << "</label>" << endl;
- if (!m_url.isEmpty())
- {
- QCString url(m_url);
- const char *refPtr = url.data();
- char *urlPtr = strchr(url.rawData(),'$');
- if (urlPtr)
- {
- *urlPtr++='\0';
- t << " <link refid=\"" << convertToXML(urlPtr) << "\"";
- if (*refPtr!='\0')
- {
- t << " external=\"" << convertToXML(refPtr) << "\"";
- }
- t << "/>" << endl;
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> nli(*m_children);
- QListIterator<EdgeInfo> eli(*m_edgeInfo);
- DotNode *childNode;
- EdgeInfo *edgeInfo;
- for (;(childNode=nli.current());++nli,++eli)
- {
- edgeInfo=eli.current();
- t << " <childnode refid=\"" << childNode->m_number << "\" relation=\"";
- if (isClassGraph)
- {
- switch(edgeInfo->m_color)
- {
- case EdgeInfo::Blue: t << "public-inheritance"; break;
- case EdgeInfo::Green: t << "protected-inheritance"; break;
- case EdgeInfo::Red: t << "private-inheritance"; break;
- case EdgeInfo::Purple: t << "usage"; break;
- case EdgeInfo::Orange: t << "template-instance"; break;
- case EdgeInfo::Orange2: t << "type-constraint"; break;
- case EdgeInfo::Grey: ASSERT(0); break;
- }
- }
- else // include graph
- {
- t << "include";
- }
- t << "\">" << endl;
- if (!edgeInfo->m_label.isEmpty())
- {
- int p=0;
- int ni;
- while ((ni=edgeInfo->m_label.find('\n',p))!=-1)
- {
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.mid(p,ni-p))
- << "</edgelabel>" << endl;
- p=ni+1;
- }
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.right(edgeInfo->m_label.length()-p))
- << "</edgelabel>" << endl;
- }
- t << " </childnode>" << endl;
- }
- }
- t << " </node>" << endl;
-}
-
-void DotNode::writeDocbook(FTextStream &t,bool isClassGraph)
-{
- t << " <node id=\"" << m_number << "\">" << endl;
- t << " <label>" << convertToXML(m_label) << "</label>" << endl;
- if (!m_url.isEmpty())
- {
- QCString url(m_url);
- const char *refPtr = url.data();
- char *urlPtr = strchr(url.rawData(),'$');
- if (urlPtr)
- {
- *urlPtr++='\0';
- t << " <link refid=\"" << convertToXML(urlPtr) << "\"";
- if (*refPtr!='\0')
- {
- t << " external=\"" << convertToXML(refPtr) << "\"";
- }
- t << "/>" << endl;
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> nli(*m_children);
- QListIterator<EdgeInfo> eli(*m_edgeInfo);
- DotNode *childNode;
- EdgeInfo *edgeInfo;
- for (;(childNode=nli.current());++nli,++eli)
- {
- edgeInfo=eli.current();
- t << " <childnode refid=\"" << childNode->m_number << "\" relation=\"";
- if (isClassGraph)
- {
- switch(edgeInfo->m_color)
- {
- case EdgeInfo::Blue: t << "public-inheritance"; break;
- case EdgeInfo::Green: t << "protected-inheritance"; break;
- case EdgeInfo::Red: t << "private-inheritance"; break;
- case EdgeInfo::Purple: t << "usage"; break;
- case EdgeInfo::Orange: t << "template-instance"; break;
- case EdgeInfo::Orange2: t << "type-constraint"; break;
- case EdgeInfo::Grey: ASSERT(0); break;
- }
- }
- else // include graph
- {
- t << "include";
- }
- t << "\">" << endl;
- if (!edgeInfo->m_label.isEmpty())
- {
- int p=0;
- int ni;
- while ((ni=edgeInfo->m_label.find('\n',p))!=-1)
- {
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.mid(p,ni-p))
- << "</edgelabel>" << endl;
- p=ni+1;
- }
- t << " <edgelabel>"
- << convertToXML(edgeInfo->m_label.right(edgeInfo->m_label.length()-p))
- << "</edgelabel>" << endl;
- }
- t << " </childnode>" << endl;
- }
- }
- t << " </node>" << endl;
-}
-
-
-void DotNode::writeDEF(FTextStream &t)
-{
- const char* nodePrefix = " node-";
-
- t << " node = {" << endl;
- t << nodePrefix << "id = " << m_number << ';' << endl;
- t << nodePrefix << "label = '" << m_label << "';" << endl;
-
- if (!m_url.isEmpty())
- {
- QCString url(m_url);
- const char *refPtr = url.data();
- char *urlPtr = strchr(url.rawData(),'$');
- if (urlPtr)
- {
- *urlPtr++='\0';
- t << nodePrefix << "link = {" << endl << " "
- << nodePrefix << "link-id = '" << urlPtr << "';" << endl;
-
- if (*refPtr!='\0')
- {
- t << " " << nodePrefix << "link-external = '"
- << refPtr << "';" << endl;
- }
- t << " };" << endl;
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> nli(*m_children);
- QListIterator<EdgeInfo> eli(*m_edgeInfo);
- DotNode *childNode;
- EdgeInfo *edgeInfo;
- for (;(childNode=nli.current());++nli,++eli)
- {
- edgeInfo=eli.current();
- t << " node-child = {" << endl;
- t << " child-id = '" << childNode->m_number << "';" << endl;
- t << " relation = ";
-
- switch(edgeInfo->m_color)
- {
- case EdgeInfo::Blue: t << "public-inheritance"; break;
- case EdgeInfo::Green: t << "protected-inheritance"; break;
- case EdgeInfo::Red: t << "private-inheritance"; break;
- case EdgeInfo::Purple: t << "usage"; break;
- case EdgeInfo::Orange: t << "template-instance"; break;
- case EdgeInfo::Orange2: t << "type-constraint"; break;
- case EdgeInfo::Grey: ASSERT(0); break;
- }
- t << ';' << endl;
-
- if (!edgeInfo->m_label.isEmpty())
- {
- t << " edgelabel = <<_EnD_oF_dEf_TeXt_" << endl
- << edgeInfo->m_label << endl
- << "_EnD_oF_dEf_TeXt_;" << endl;
- }
- t << " }; /* node-child */" << endl;
- } /* for (;childNode...) */
- }
- t << " }; /* node */" << endl;
-}
-
-
-void DotNode::clearWriteFlag()
-{
- m_written=FALSE;
- if (m_parents!=0)
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- if (pn->m_written)
- {
- pn->clearWriteFlag();
- }
- }
- }
- if (m_children!=0)
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- if (cn->m_written)
- {
- cn->clearWriteFlag();
- }
- }
- }
-}
-
-void DotNode::colorConnectedNodes(int curColor)
-{
- if (m_children)
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- if (cn->m_subgraphId==-1) // uncolored child node
- {
- cn->m_subgraphId=curColor;
- cn->markAsVisible();
- cn->colorConnectedNodes(curColor);
- //printf("coloring node %s (%p): %d\n",cn->m_label.data(),cn,cn->m_subgraphId);
- }
- }
- }
-
- if (m_parents)
- {
- QListIterator<DotNode> dnlip(*m_parents);
- DotNode *pn;
- for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
- {
- if (pn->m_subgraphId==-1) // uncolored parent node
- {
- pn->m_subgraphId=curColor;
- pn->markAsVisible();
- pn->colorConnectedNodes(curColor);
- //printf("coloring node %s (%p): %d\n",pn->m_label.data(),pn,pn->m_subgraphId);
- }
- }
- }
-}
-
-void DotNode::renumberNodes(int &number)
-{
- m_number = number++;
- if (m_children)
- {
- QListIterator<DotNode> dnlic(*m_children);
- DotNode *cn;
- for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
- {
- if (!cn->m_renumbered)
- {
- cn->m_renumbered = true;
- cn->renumberNodes(number);
- }
- }
- }
-}
-
-const DotNode *DotNode::findDocNode() const
-{
- if (!m_url.isEmpty()) return this;
- //printf("findDocNode(): `%s'\n",m_label.data());
- if (m_parents)
- {
- QListIterator<DotNode> dnli(*m_parents);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
- {
- if (!pn->m_hasDoc)
- {
- pn->m_hasDoc=TRUE;
- const DotNode *dn = pn->findDocNode();
- if (dn) return dn;
- }
- }
- }
- if (m_children)
- {
- QListIterator<DotNode> dnli(*m_children);
- DotNode *cn;
- for (dnli.toFirst();(cn=dnli.current());++dnli)
- {
- if (!cn->m_hasDoc)
- {
- cn->m_hasDoc=TRUE;
- const DotNode *dn = cn->findDocNode();
- if (dn) return dn;
- }
- }
- }
- return 0;
-}
-
-//--------------------------------------------------------------------
-
-void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out,
- const char *path,const char *fileName,int id) const
-{
- QDir d(path);
- QCString baseName;
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- if (m_prefix.isEmpty())
- baseName.sprintf("inherit_graph_%d",id);
- else
- baseName.sprintf("%sinherit_graph_%d",m_prefix.data(),id);
- QCString imgName = baseName+"."+ imgExt;
- QCString mapName = baseName+".map";
- QCString absImgName = QCString(d.absPath().data())+"/"+imgName;
- QCString absMapName = QCString(d.absPath().data())+"/"+mapName;
- QCString absBaseName = QCString(d.absPath().data())+"/"+baseName;
- QListIterator<DotNode> dnli2(*m_rootNodes);
- DotNode *node;
-
- // compute md5 checksum of the graph were are about to generate
- QGString theGraph;
- FTextStream md5stream(&theGraph);
- writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
- md5stream << " rankdir=\"LR\";" << endl;
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->clearWriteFlag();
- }
- }
- for (dnli2.toFirst();(node=dnli2.current());++dnli2)
- {
- if (node->m_subgraphId==n->m_subgraphId)
- {
- node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE);
- }
- }
- writeGraphFooter(md5stream);
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.rawData(),33);
- bool regenerate=FALSE;
- if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
- !checkDeliverables(absImgName,absMapName))
- {
- regenerate=TRUE;
- // image was new or has changed
- QCString dotName=absBaseName+".dot";
- QFile f(dotName);
- if (!f.open(IO_WriteOnly)) return;
- FTextStream t(&f);
- t << theGraph;
- f.close();
-
- DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
- }
- else
- {
- removeDotGraph(absBaseName+".dot");
- }
- Doxygen::indexList->addImageFile(imgName);
- // write image and map in a table row
- QCString mapLabel = escapeCharsInString(n->m_label,FALSE);
- if (imgExt=="svg") // vector graphics
- {
- if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName))
- {
- if (regenerate)
- {
- DotManager::instance()->addSVGConversion(absImgName,QCString(),
- FALSE,QCString(),FALSE,0);
- }
- 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;
- }
- }
-}
-
-void DotGfxHierarchyTable::writeGraph(FTextStream &out,
- const char *path,const char *fileName) const
-{
- //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
- //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
-
- if (m_rootSubgraphs->count()==0) return;
-
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
-
- // put each connected subgraph of the hierarchy in a row of the HTML output
- out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl;
-
- QListIterator<DotNode> dnli(*m_rootSubgraphs);
- DotNode *n;
- int count=0;
- for (dnli.toFirst();(n=dnli.current());++dnli)
- {
- out << "<tr><td>";
- createGraph(n,out,path,fileName,count++);
- out << "</td></tr>" << endl;
- }
- out << "</table>" << endl;
-}
-
-void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper)
-{
- //printf("addHierarchy `%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count());
- if (cd->subClasses())
- {
- BaseClassListIterator bcli(*cd->subClasses());
- BaseClassDef *bcd;
- for ( ; (bcd=bcli.current()) ; ++bcli )
- {
- ClassDef *bClass=bcd->classDef;
- //printf(" Trying sub class=`%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count());
- if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses()))
- {
- DotNode *bn;
- //printf(" Node `%s' Found visible class=`%s'\n",n->m_label.data(),
- // bClass->name().data());
- if ((bn=m_usedNodes->find(bClass->name()))) // node already present
- {
- if (n->m_children==0 || n->m_children->findRef(bn)==-1) // no arrow yet
- {
- n->addChild(bn,bcd->prot);
- bn->addParent(n);
- //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n",
- // n->m_label.data(),
- // bn->m_label.data(),
- // bn->m_children ? bn->m_children->count() : 0,
- // bn->m_parents ? bn->m_parents->count() : 0
- // );
- }
- //else
- //{
- // printf(" Class already has an arrow!\n");
- //}
- }
- else
- {
- QCString tmp_url="";
- if (bClass->isLinkable() && !bClass->isHidden())
- {
- tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase();
- if (!bClass->anchor().isEmpty())
- {
- tmp_url+="#"+bClass->anchor();
- }
- }
- QCString tooltip = bClass->briefDescriptionAsTooltip();
- bn = new DotNode(m_curNodeNumber++,
- bClass->displayName(),
- tooltip,
- tmp_url.data()
- );
- n->addChild(bn,bcd->prot);
- bn->addParent(n);
- //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n",
- // n->m_label.data(),
- // bn->m_label.data(),
- // bn->m_children ? bn->m_children->count() : 0,
- // bn->m_parents ? bn->m_parents->count() : 0
- // );
- //printf(" inserting %s (%p)\n",bClass->name().data(),bn);
- m_usedNodes->insert(bClass->name(),bn); // add node to the used list
- }
- if (!bClass->isVisited() && !hideSuper && bClass->subClasses())
- {
- bool wasVisited=bClass->isVisited();
- bClass->setVisited(TRUE);
- addHierarchy(bn,bClass,wasVisited);
- }
- }
- }
- }
- //printf("end addHierarchy\n");
-}
-
-void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
-{
- static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
- ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
- for (cli.toLast();(cd=cli.current());--cli)
- {
- //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count());
- if (cd->getLanguage()==SrcLangExt_VHDL &&
- (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS
- )
- {
- continue;
- }
- if (sliceOpt && cd->compoundType() != m_classType)
- {
- continue;
- }
- if (!hasVisibleRoot(cd->baseClasses()) &&
- cd->isVisibleInHierarchy()
- ) // root node in the forest
- {
- QCString tmp_url="";
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- if (!cd->anchor().isEmpty())
- {
- tmp_url+="#"+cd->anchor();
- }
- }
- //printf("Inserting root class %s\n",cd->name().data());
- QCString tooltip = cd->briefDescriptionAsTooltip();
- DotNode *n = new DotNode(m_curNodeNumber++,
- cd->displayName(),
- tooltip,
- tmp_url.data());
-
- //m_usedNodes->clear();
- m_usedNodes->insert(cd->name(),n);
- m_rootNodes->insert(0,n);
- if (!cd->isVisited() && cd->subClasses())
- {
- addHierarchy(n,cd,cd->isVisited());
- cd->setVisited(TRUE);
- }
- }
- }
-}
-
-DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::CompoundType ct)
- : m_prefix(prefix)
- , m_classType(ct)
- , m_curNodeNumber(1)
-{
- m_rootNodes = new QList<DotNode>;
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->setAutoDelete(TRUE);
- m_rootSubgraphs = new DotNodeList;
-
- // build a graph with each class as a node and the inheritance relations
- // as edges
- initClassHierarchy(Doxygen::classSDict);
- initClassHierarchy(Doxygen::hiddenClasses);
- addClassList(Doxygen::classSDict);
- addClassList(Doxygen::hiddenClasses);
- // m_usedNodes now contains all nodes in the graph
-
- // color the graph into a set of independent subgraphs
- bool done=FALSE;
- int curColor=0;
- QListIterator<DotNode> dnli(*m_rootNodes);
- while (!done) // there are still nodes to color
- {
- DotNode *n;
- done=TRUE; // we are done unless there are still uncolored nodes
- for (dnli.toLast();(n=dnli.current());--dnli)
- {
- if (n->m_subgraphId==-1) // not yet colored
- {
- //printf("Starting at node %s (%p): %d\n",n->m_label.data(),n,curColor);
- done=FALSE; // still uncolored nodes
- n->m_subgraphId=curColor;
- n->markAsVisible();
- n->colorConnectedNodes(curColor);
- curColor++;
- const DotNode *dn=n->findDocNode();
- if (dn!=0)
- m_rootSubgraphs->inSort(dn);
- else
- m_rootSubgraphs->inSort(n);
- }
- }
- }
-
- //printf("Number of independent subgraphs: %d\n",curColor);
- QListIterator<DotNode> dnli2(*m_rootSubgraphs);
- DotNode *n;
- for (dnli2.toFirst();(n=dnli2.current());++dnli2)
- {
- //printf("Node %s color=%d (c=%d,p=%d)\n",
- // n->m_label.data(),n->m_subgraphId,
- // n->m_children?n->m_children->count():0,
- // n->m_parents?n->m_parents->count():0);
- int number=0;
- n->renumberNodes(number);
- }
-}
-
-DotGfxHierarchyTable::~DotGfxHierarchyTable()
-{
- //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n");
-
- //QDictIterator<DotNode> di(*m_usedNodes);
- //DotNode *n;
- //for (;(n=di.current());++di)
- //{
- // printf("Node %p: %s\n",n,n->label().data());
- //}
-
- delete m_rootNodes;
- delete m_usedNodes;
- delete m_rootSubgraphs;
-}
-
-//--------------------------------------------------------------------
-
-void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot,
- const char *label,const char *usedName,const char *templSpec,bool base,int distance)
-{
- if (Config_getBool(HIDE_UNDOC_CLASSES) && !cd->isLinkable()) return;
-
- int edgeStyle = (label || prot==EdgeInfo::Orange || prot==EdgeInfo::Orange2) ? EdgeInfo::Dashed : EdgeInfo::Solid;
- QCString className;
- if (cd->isAnonymous())
- {
- className="anonymous:";
- className+=label;
- }
- else if (usedName) // name is a typedef
- {
- className=usedName;
- }
- else if (templSpec) // name has a template part
- {
- className=insertTemplateSpecifierInScope(cd->name(),templSpec);
- }
- else // just a normal name
- {
- className=cd->displayName();
- }
- //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n",
- // className.data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base);
- DotNode *bn = m_usedNodes->find(className);
- if (bn) // class already inserted
- {
- if (base)
- {
- n->addChild(bn,prot,edgeStyle,label);
- bn->addParent(n);
- }
- else
- {
- bn->addChild(n,prot,edgeStyle,label);
- n->addParent(bn);
- }
- bn->setDistance(distance);
- //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data());
- }
- else // new class
- {
- QCString displayName=className;
- if (Config_getBool(HIDE_SCOPE_NAMES)) displayName=stripScope(displayName);
- QCString tmp_url;
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- if (!cd->anchor().isEmpty())
- {
- tmp_url+="#"+cd->anchor();
- }
- }
- QCString tooltip = cd->briefDescriptionAsTooltip();
- bn = new DotNode(m_curNodeNumber++,
- displayName,
- tooltip,
- tmp_url.data(),
- FALSE, // rootNode
- cd
- );
- if (base)
- {
- n->addChild(bn,prot,edgeStyle,label);
- bn->addParent(n);
- }
- else
- {
- bn->addChild(n,prot,edgeStyle,label);
- n->addParent(bn);
- }
- bn->setDistance(distance);
- m_usedNodes->insert(className,bn);
- //printf(" add new child node `%s' to %s hidden=%d url=%s\n",
- // className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data());
-
- buildGraph(cd,bn,base,distance+1);
- }
-}
-
-void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includeParents)
-{
- while (queue.count()>0)
- {
- DotNode *n = queue.take(0);
- if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
- {
- bool truncated = FALSE;
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- if (!dn->isVisible())
- truncated = TRUE;
- else
- queue.append(dn);
- }
- }
- if (n->m_parents && includeParents)
- {
- QListIterator<DotNode> li(*n->m_parents);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- if (!dn->isVisible())
- truncated = TRUE;
- else
- queue.append(dn);
- }
- }
- n->markAsTruncated(truncated);
- }
- }
-}
-
-bool DotClassGraph::determineVisibleNodes(DotNode *rootNode,
- int maxNodes,bool includeParents)
+class GraphLegendDotGraph : public DotGraph
{
- QList<DotNode> childQueue;
- QList<DotNode> parentQueue;
- QArray<int> childTreeWidth;
- QArray<int> parentTreeWidth;
- childQueue.append(rootNode);
- if (includeParents) parentQueue.append(rootNode);
- bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop
- // despite being marked visible in the child loop
- while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0)
- {
- static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH);
- if (childQueue.count()>0)
- {
- DotNode *n = childQueue.take(0);
- int distance = n->distance();
- if (!n->isVisible() && distance<=maxDistance) // not yet processed
- {
- if (distance>0)
- {
- int oldSize=(int)childTreeWidth.size();
- if (distance>oldSize)
- {
- childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance));
- int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0;
- }
- childTreeWidth[distance-1]+=n->label().length();
- }
- n->markAsVisible();
- maxNodes--;
- // add direct children
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- childQueue.append(dn);
- }
- }
- }
- }
- if (includeParents && parentQueue.count()>0)
- {
- DotNode *n = parentQueue.take(0);
- if ((!n->isVisible() || firstNode) && n->distance()<=maxDistance) // not yet processed
- {
- firstNode=FALSE;
- int distance = n->distance();
- if (distance>0)
- {
- int oldSize = (int)parentTreeWidth.size();
- if (distance>oldSize)
- {
- parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance));
- int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0;
- }
- parentTreeWidth[distance-1]+=n->label().length();
- }
- n->markAsVisible();
- maxNodes--;
- // add direct parents
- if (n->m_parents)
- {
- QListIterator<DotNode> li(*n->m_parents);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- parentQueue.append(dn);
- }
- }
- }
- }
- }
- if (Config_getBool(UML_LOOK)) return FALSE; // UML graph are always top to bottom
- int maxWidth=0;
- int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size());
- uint i;
- for (i=0;i<childTreeWidth.size();i++)
- {
- if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i);
- }
- for (i=0;i<parentTreeWidth.size();i++)
- {
- if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i);
- }
- //printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight);
- return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree
- // from left to right instead of top to bottom,
- // with the idea to render very wide trees in
- // left to right order.
-}
-
-void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base,int distance)
-{
- static bool templateRelations = Config_getBool(TEMPLATE_RELATIONS);
- //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n",
- // cd->name().data(),distance,base);
- // ---- Add inheritance relations
-
- if (m_graphType == DotNode::Inheritance || m_graphType==DotNode::Collaboration)
- {
- BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses();
- if (bcl)
- {
- BaseClassListIterator bcli(*bcl);
- BaseClassDef *bcd;
- for ( ; (bcd=bcli.current()) ; ++bcli )
- {
- //printf("-------- inheritance relation %s->%s templ=`%s'\n",
- // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data());
- addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName,
- bcd->templSpecifiers,base,distance);
- }
- }
- }
- if (m_graphType == DotNode::Collaboration)
- {
- // ---- Add usage relations
-
- UsesClassDict *dict =
- base ? cd->usedImplementationClasses() :
- cd->usedByImplementationClasses()
- ;
- if (dict)
- {
- UsesClassDictIterator ucdi(*dict);
- UsesClassDef *ucd;
- for (;(ucd=ucdi.current());++ucdi)
- {
- QCString label;
- QDictIterator<void> dvi(*ucd->accessors);
- const char *s;
- bool first=TRUE;
- int count=0;
- int maxLabels=10;
- for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
- {
- if (first)
- {
- label=s;
- first=FALSE;
- }
- else
- {
- label+=QCString("\n")+s;
- }
- }
- if (count==maxLabels) label+="\n...";
- //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
- addClass(ucd->classDef,n,EdgeInfo::Purple,label,0,
- ucd->templSpecifiers,base,distance);
- }
- }
- }
- if (templateRelations && base)
- {
- ConstraintClassDict *dict = cd->templateTypeConstraints();
- if (dict)
- {
- ConstraintClassDictIterator ccdi(*dict);
- ConstraintClassDef *ccd;
- for (;(ccd=ccdi.current());++ccdi)
- {
- QCString label;
- QDictIterator<void> dvi(*ccd->accessors);
- const char *s;
- bool first=TRUE;
- int count=0;
- int maxLabels=10;
- for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
- {
- if (first)
- {
- label=s;
- first=FALSE;
- }
- else
- {
- label+=QCString("\n")+s;
- }
- }
- if (count==maxLabels) label+="\n...";
- //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
- addClass(ccd->classDef,n,EdgeInfo::Orange2,label,0,
- 0,TRUE,distance);
- }
- }
- }
-
- // ---- Add template instantiation relations
-
- if (templateRelations)
- {
- if (base) // template relations for base classes
- {
- ClassDef *templMaster=cd->templateMaster();
- if (templMaster)
- {
- QDictIterator<ClassDef> cli(*templMaster->getTemplateInstances());
- ClassDef *templInstance;
- for (;(templInstance=cli.current());++cli)
- {
- if (templInstance==cd)
- {
- addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0,
- 0,TRUE,distance);
- }
- }
- }
- }
- else // template relations for super classes
+ private:
+ virtual QCString getBaseName() const
{
- QDict<ClassDef> *templInstances = cd->getTemplateInstances();
- if (templInstances)
- {
- QDictIterator<ClassDef> cli(*templInstances);
- ClassDef *templInstance;
- for (;(templInstance=cli.current());++cli)
- {
- addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0,
- 0,FALSE,distance);
- }
- }
+ return "graph_legend";
}
- }
-}
-
-int DotClassGraph::m_curNodeNumber = 0;
-void DotClassGraph::resetNumbering()
-{
- m_curNodeNumber = 0;
-}
-
-DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t)
-{
- //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data());
- m_graphType = t;
- QCString tmp_url="";
- if (cd->isLinkable() && !cd->isHidden())
- {
- tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
- if (!cd->anchor().isEmpty())
+ virtual void computeTheGraph()
{
- tmp_url+="#"+cd->anchor();
+ FTextStream md5stream(&m_theGraph);
+ writeGraphHeader(md5stream,theTranslator->trLegendTitle());
+ md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n";
+ md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"grey75\"];\n";
+ md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
+ md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << DOT_FONTNAME << "\"];\n";
+ md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n";
+ writeGraphFooter(md5stream);
}
- }
- QCString className = cd->displayName();
- QCString tooltip = cd->briefDescriptionAsTooltip();
- m_startNode = new DotNode(m_curNodeNumber++,
- className,
- tooltip,
- tmp_url.data(),
- TRUE, // is a root node
- cd
- );
- m_startNode->setDistance(0);
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(className,m_startNode);
-
- //printf("Root node %s\n",cd->name().data());
- //if (m_recDepth>0)
- //{
- buildGraph(cd,m_startNode,TRUE,1);
- if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1);
- //}
-
- static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- //int directChildNodes = 1;
- //if (m_startNode->m_children!=0)
- // directChildNodes+=m_startNode->m_children->count();
- //if (t==DotNode::Inheritance && m_startNode->m_parents!=0)
- // directChildNodes+=m_startNode->m_parents->count();
- //if (directChildNodes>maxNodes) maxNodes=directChildNodes;
- //openNodeQueue.append(m_startNode);
- m_lrRank = determineVisibleNodes(m_startNode,maxNodes,t==DotNode::Inheritance);
- QList<DotNode> openNodeQueue;
- openNodeQueue.append(m_startNode);
- determineTruncatedNodes(openNodeQueue,t==DotNode::Inheritance);
-
- m_collabFileName = cd->collaborationGraphFileName();
- m_inheritFileName = cd->inheritanceGraphFileName();
-}
-
-bool DotClassGraph::isTrivial() const
-{
- static bool umlLook = Config_getBool(UML_LOOK);
- if (m_graphType==DotNode::Inheritance)
- return m_startNode->m_children==0 && m_startNode->m_parents==0;
- else
- return !umlLook && m_startNode->m_children==0;
-}
-
-bool DotClassGraph::isTooBig() const
-{
- static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- int numNodes = 0;
- numNodes+= m_startNode->m_children ? m_startNode->m_children->count() : 0;
- if (m_graphType==DotNode::Inheritance)
- {
- numNodes+= m_startNode->m_parents ? m_startNode->m_parents->count() : 0;
- }
- return numNodes>=maxNodes;
-}
-
-DotClassGraph::~DotClassGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-/*! Computes a 16 byte md5 checksum for a given dot graph.
- * The md5 checksum is returned as a 32 character ASCII string.
- */
-QCString computeMd5Signature(DotNode *root,
- DotNode::GraphType gt,
- GraphOutputFormat format,
- const QCString &rank, // either "LR", "RL", or ""
- bool renderParents,
- bool backArrows,
- const QCString &title,
- QCString &graphStr
- )
-{
- //printf("computeMd5Signature\n");
- QGString buf;
- FTextStream md5stream(&buf);
- writeGraphHeader(md5stream,title);
- if (!rank.isEmpty())
- {
- md5stream << " rankdir=\"" << rank << "\";" << endl;
- }
- root->clearWriteFlag();
- root->write(md5stream,
- gt,
- format,
- gt!=DotNode::CallGraph && gt!=DotNode::Dependency,
- TRUE,
- backArrows);
- if (renderParents && root->m_parents)
- {
- QListIterator<DotNode> dnli(*root->m_parents);
- DotNode *pn;
- for (dnli.toFirst();(pn=dnli.current());++dnli)
+ virtual QCString getMapLabel() const
{
- if (pn->isVisible())
- {
- root->writeArrow(md5stream, // stream
- gt, // graph type
- format, // output format
- pn, // child node
- pn->m_edgeInfo->at(pn->m_children->findRef(root)), // edge info
- FALSE, // topDown?
- backArrows // point back?
- );
- }
- pn->write(md5stream, // stream
- gt, // graph type
- format, // output format
- TRUE, // topDown?
- FALSE, // toChildren?
- backArrows // backward pointing arrows?
- );
+ return "";
}
- }
- writeGraphFooter(md5stream);
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)buf.data(),buf.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.rawData(),33);
- graphStr=buf.data();
- //printf("md5: %s | file: %s\n",sigStr,baseName.data());
- return sigStr;
-}
-static bool updateDotGraph(DotNode *root,
- DotNode::GraphType gt,
- const QCString &baseName,
- GraphOutputFormat format,
- const QCString &rank,
- bool renderParents,
- bool backArrows,
- const QCString &title=QCString()
- )
-{
- QCString theGraph;
- // TODO: write graph to theGraph, then compute md5 checksum
- QCString md5 = computeMd5Signature(
- root,gt,format,rank,renderParents,
- backArrows,title,theGraph);
- QFile f(baseName+".dot");
- if (f.open(IO_WriteOnly))
- {
- FTextStream t(&f);
- t << theGraph;
- }
- return checkAndUpdateMd5Signature(baseName,md5); // graph needs to be regenerated
-}
-
-QCString DotClassGraph::writeGraph(FTextStream &out,
- GraphOutputFormat graphFormat,
- EmbeddedOutputFormat textFormat,
- const char *path,
- const char *fileName,
- const char *relPath,
- bool /*isTBRank*/,
- bool generateImageMap,
- int graphId) const
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
- static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
-
- QCString baseName;
- QCString mapName;
- switch (m_graphType)
- {
- case DotNode::Collaboration:
- mapName="coll_map";
- baseName=m_collabFileName;
- break;
- case DotNode::Inheritance:
- mapName="inherit_map";
- baseName=m_inheritFileName;
- break;
- default:
- ASSERT(0);
- break;
- }
-
- // derive target file names from baseName
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString absBaseName = d.absPath().utf8()+"/"+baseName;
- QCString absDotName = absBaseName+".dot";
- QCString absMapName = absBaseName+".map";
- QCString absPdfName = absBaseName+".pdf";
- QCString absEpsName = absBaseName+".eps";
- QCString absImgName = absBaseName+"."+imgExt;
-
- bool regenerate = FALSE;
- if (updateDotGraph(m_startNode,
- m_graphType,
- absBaseName,
- graphFormat,
- m_lrRank ? "LR" : "",
- m_graphType==DotNode::Inheritance,
- TRUE,
- m_startNode->label()
- ) ||
- !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
- usePDFLatex ? absPdfName : absEpsName,
- graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString())
- )
- {
- regenerate=TRUE;
- if (graphFormat==GOF_BITMAP) // run dot to create a bitmap image
- {
- DotRunner *dotRun = new DotRunner(absDotName,
- d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
-
- }
- else if (graphFormat==GOF_EPS) // run dot to create a .eps image
- {
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- if (usePDFLatex)
- {
- dotRun->addJob("pdf",absPdfName,absBaseName);
- }
- else
- {
- dotRun->addJob("ps",absEpsName);
- }
- DotManager::instance()->addRun(dotRun);
- }
- }
- Doxygen::indexList->addImageFile(baseName+"."+imgExt);
-
- if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
- {
- out << "<para>" << endl;
- out << " <informalfigure>" << endl;
- out << " <mediaobject>" << endl;
- out << " <imageobject>" << endl;
- out << " <imagedata";
- out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
- out << "</imagedata>" << endl;
- out << " </imageobject>" << endl;
- out << " </mediaobject>" << endl;
- out << " </informalfigure>" << endl;
- out << "</para>" << endl;
- }
- else if (graphFormat==GOF_BITMAP && generateImageMap) // produce HTML to include the image
- {
- QCString mapLabel = escapeCharsInString(m_startNode->m_label,FALSE)+"_"+
- escapeCharsInString(mapName,FALSE);
- if (imgExt=="svg") // add link to SVG file without map file
- {
- 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(),TRUE,graphId);
- }
- int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath);
- out << "<!-- SVG " << mapId << " -->" << endl;
- }
- out << "</div>" << endl;
- }
- else // add link to bitmap file with image map
- {
- 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 (graphFormat==GOF_EPS) // produce tex to include the .eps image
- {
- if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
- {
- int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE /*TRUE*/);
- out << endl << "% FIG " << figId << endl;
- }
- }
- if (!regenerate) removeDotGraph(absDotName);
-
- return baseName;
-}
-
-//--------------------------------------------------------------------
-
-void DotClassGraph::writeXML(FTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeXML(t,TRUE);
- }
-}
-
-void DotClassGraph::writeDocbook(FTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeDocbook(t,TRUE);
- }
-}
-
-void DotClassGraph::writeDEF(FTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeDEF(t);
- }
-}
-
-//--------------------------------------------------------------------
-
-void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance)
-{
- QList<IncludeInfo> *includeFiles =
- m_inverse ? fd->includedByFileList() : fd->includeFileList();
- if (includeFiles)
- {
- QListIterator<IncludeInfo> ili(*includeFiles);
- IncludeInfo *ii;
- for (;(ii=ili.current());++ili)
- {
- FileDef *bfd = ii->fileDef;
- QCString in = ii->includeName;
- //printf(">>>> in=`%s' bfd=%p\n",ii->includeName.data(),bfd);
- bool doc=TRUE,src=FALSE;
- if (bfd)
- {
- in = bfd->absFilePath();
- doc = bfd->isLinkable() && !bfd->isHidden();
- src = bfd->generateSourceFile();
- }
- if (doc || src || !Config_getBool(HIDE_UNDOC_RELATIONS))
- {
- QCString url="";
- if (bfd) url=bfd->getOutputFileBase().copy();
- if (!doc && src)
- {
- url=bfd->getSourceFileBase();
- }
- DotNode *bn = m_usedNodes->find(in);
- if (bn) // file is already a node in the graph
- {
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- bn->setDistance(distance);
- }
- else
- {
- QCString tmp_url;
- QCString tooltip;
- if (bfd)
- {
- tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString();
- tooltip = bfd->briefDescriptionAsTooltip();
- }
- bn = new DotNode(
- m_curNodeNumber++, // n
- ii->includeName, // label
- tooltip, // tip
- tmp_url, // url
- FALSE, // rootNode
- 0 // cd
- );
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- m_usedNodes->insert(in,bn);
- bn->setDistance(distance);
-
- if (bfd) buildGraph(bn,bfd,distance+1);
- }
- }
- }
- }
-}
-
-void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes)
-{
- while (queue.count()>0 && maxNodes>0)
- {
- static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH);
- DotNode *n = queue.take(0);
- if (!n->isVisible() && n->distance()<=maxDistance) // not yet processed
- {
- n->markAsVisible();
- maxNodes--;
- // add direct children
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- queue.append(dn);
- }
- }
- }
- }
-}
-
-void DotInclDepGraph::determineTruncatedNodes(QList<DotNode> &queue)
-{
- while (queue.count()>0)
- {
- DotNode *n = queue.take(0);
- if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
- {
- bool truncated = FALSE;
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- if (!dn->isVisible())
- truncated = TRUE;
- else
- queue.append(dn);
- }
- }
- n->markAsTruncated(truncated);
- }
- }
-}
-
-int DotInclDepGraph::m_curNodeNumber = 0;
-
-void DotInclDepGraph::resetNumbering()
-{
- m_curNodeNumber = 0;
-}
-
-DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse)
-{
- m_inverse = inverse;
- ASSERT(fd!=0);
- m_inclDepFileName = fd->includeDependencyGraphFileName();
- m_inclByDepFileName = fd->includedByDependencyGraphFileName();
- QCString tmp_url=fd->getReference()+"$"+fd->getOutputFileBase();
- QCString tooltip = fd->briefDescriptionAsTooltip();
- m_startNode = new DotNode(m_curNodeNumber++,
- fd->docName(),
- tooltip,
- tmp_url.data(),
- TRUE // root node
- );
- m_startNode->setDistance(0);
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(fd->absFilePath(),m_startNode);
- buildGraph(m_startNode,fd,1);
-
- static int nodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- int maxNodes = nodes;
- //int directChildNodes = 1;
- //if (m_startNode->m_children!=0)
- // directChildNodes+=m_startNode->m_children->count();
- //if (directChildNodes>maxNodes) maxNodes=directChildNodes;
- QList<DotNode> openNodeQueue;
- openNodeQueue.append(m_startNode);
- determineVisibleNodes(openNodeQueue,maxNodes);
- openNodeQueue.clear();
- openNodeQueue.append(m_startNode);
- determineTruncatedNodes(openNodeQueue);
-}
-
-DotInclDepGraph::~DotInclDepGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-
-QCString DotInclDepGraph::writeGraph(FTextStream &out,
- GraphOutputFormat graphFormat,
- EmbeddedOutputFormat textFormat,
- const char *path,
- const char *fileName,
- const char *relPath,
- bool generateImageMap,
- int graphId
- ) const
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
- static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
-
- QCString baseName;
- if (m_inverse)
- {
- baseName=m_inclByDepFileName;
- }
- else
- {
- baseName=m_inclDepFileName;
- }
- QCString mapName=escapeCharsInString(m_startNode->m_label,FALSE);
- if (m_inverse) mapName+="dep";
-
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString absBaseName = d.absPath().utf8()+"/"+baseName;
- QCString absDotName = absBaseName+".dot";
- QCString absMapName = absBaseName+".map";
- QCString absPdfName = absBaseName+".pdf";
- QCString absEpsName = absBaseName+".eps";
- QCString absImgName = absBaseName+"."+imgExt;
-
- bool regenerate = FALSE;
- if (updateDotGraph(m_startNode,
- DotNode::Dependency,
- absBaseName,
- graphFormat,
- "", // lrRank
- FALSE, // renderParents
- m_inverse, // backArrows
- m_startNode->label()
- ) ||
- !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
- usePDFLatex ? absPdfName : absEpsName,
- graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString())
- )
- {
- regenerate=TRUE;
- if (graphFormat==GOF_BITMAP)
- {
- // run dot to create a bitmap image
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
- }
- else if (graphFormat==GOF_EPS)
- {
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- if (usePDFLatex)
- {
- dotRun->addJob("pdf",absPdfName,absBaseName);
- }
- else
- {
- dotRun->addJob("ps",absEpsName);
- }
- DotManager::instance()->addRun(dotRun);
- }
- }
- Doxygen::indexList->addImageFile(baseName+"."+imgExt);
-
- if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
- {
- out << "<para>" << endl;
- out << " <informalfigure>" << endl;
- out << " <mediaobject>" << endl;
- out << " <imageobject>" << endl;
- out << " <imagedata";
- out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
- out << "</imagedata>" << endl;
- out << " </imageobject>" << endl;
- out << " </mediaobject>" << endl;
- out << " </informalfigure>" << endl;
- out << "</para>" << endl;
- }
- else if (graphFormat==GOF_BITMAP && generateImageMap)
- {
- 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(),TRUE,graphId);
- }
- 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 << "</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 (graphFormat==GOF_EPS) // encapsulated postscript
- {
- if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
- {
- int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
- out << endl << "% FIG " << figId << endl;
- }
- }
- if (!regenerate) removeDotGraph(absDotName);
-
- return baseName;
-}
-
-bool DotInclDepGraph::isTrivial() const
-{
- return m_startNode->m_children==0;
-}
-
-bool DotInclDepGraph::isTooBig() const
-{
- static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0;
- return numNodes>=maxNodes;
-}
-
-void DotInclDepGraph::writeXML(FTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeXML(t,FALSE);
- }
-}
-
-void DotInclDepGraph::writeDocbook(FTextStream &t)
-{
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *node;
- for (;(node=dni.current());++dni)
- {
- node->writeDocbook(t,FALSE);
- }
-}
-
-//-------------------------------------------------------------
-
-void DotCallGraph::buildGraph(DotNode *n,MemberDef *md,int distance)
-{
- MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers();
- if (refs)
- {
- MemberSDict::Iterator mri(*refs);
- MemberDef *rmd;
- for (;(rmd=mri.current());++mri)
- {
- if (rmd->showInCallGraph())
- {
- QCString uniqueId;
- uniqueId=rmd->getReference()+"$"+
- rmd->getOutputFileBase()+"#"+rmd->anchor();
- DotNode *bn = m_usedNodes->find(uniqueId);
- if (bn) // file is already a node in the graph
- {
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- bn->setDistance(distance);
- }
- else
- {
- QCString name;
- if (Config_getBool(HIDE_SCOPE_NAMES))
- {
- name = rmd->getOuterScope()==m_scope ?
- rmd->name() : rmd->qualifiedName();
- }
- else
- {
- name = rmd->qualifiedName();
- }
- QCString tooltip = rmd->briefDescriptionAsTooltip();
- bn = new DotNode(
- m_curNodeNumber++,
- linkToText(rmd->getLanguage(),name,FALSE),
- tooltip,
- uniqueId,
- 0 //distance
- );
- n->addChild(bn,0,0,0);
- bn->addParent(n);
- bn->setDistance(distance);
- m_usedNodes->insert(uniqueId,bn);
-
- buildGraph(bn,rmd,distance+1);
- }
- }
- }
- }
-}
-
-void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes)
-{
- while (queue.count()>0 && maxNodes>0)
- {
- static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH);
- DotNode *n = queue.take(0);
- if (!n->isVisible() && n->distance()<=maxDistance) // not yet processed
- {
- n->markAsVisible();
- maxNodes--;
- // add direct children
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- queue.append(dn);
- }
- }
- }
- }
-}
-
-void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue)
-{
- while (queue.count()>0)
- {
- DotNode *n = queue.take(0);
- if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
- {
- bool truncated = FALSE;
- if (n->m_children)
- {
- QListIterator<DotNode> li(*n->m_children);
- DotNode *dn;
- for (li.toFirst();(dn=li.current());++li)
- {
- if (!dn->isVisible())
- truncated = TRUE;
- else
- queue.append(dn);
- }
- }
- n->markAsTruncated(truncated);
- }
- }
-}
-
-int DotCallGraph::m_curNodeNumber = 0;
-
-void DotCallGraph::resetNumbering()
-{
- m_curNodeNumber = 0;
-}
-
-DotCallGraph::DotCallGraph(MemberDef *md,bool inverse)
-{
- m_inverse = inverse;
- m_diskName = md->getOutputFileBase()+"_"+md->anchor();
- m_scope = md->getOuterScope();
- QCString uniqueId;
- uniqueId = md->getReference()+"$"+
- md->getOutputFileBase()+"#"+md->anchor();
- QCString name;
- if (Config_getBool(HIDE_SCOPE_NAMES))
- {
- name = md->name();
- }
- else
- {
- name = md->qualifiedName();
- }
- QCString tooltip = md->briefDescriptionAsTooltip();
- m_startNode = new DotNode(m_curNodeNumber++,
- linkToText(md->getLanguage(),name,FALSE),
- tooltip,
- uniqueId.data(),
- TRUE // root node
- );
- m_startNode->setDistance(0);
- m_usedNodes = new QDict<DotNode>(1009);
- m_usedNodes->insert(uniqueId,m_startNode);
- buildGraph(m_startNode,md,1);
-
- static int nodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- int maxNodes = nodes;
- //int directChildNodes = 1;
- //if (m_startNode->m_children!=0)
- // directChildNodes+=m_startNode->m_children->count();
- //if (directChildNodes>maxNodes) maxNodes=directChildNodes;
- QList<DotNode> openNodeQueue;
- openNodeQueue.append(m_startNode);
- determineVisibleNodes(openNodeQueue,maxNodes);
- openNodeQueue.clear();
- openNodeQueue.append(m_startNode);
- determineTruncatedNodes(openNodeQueue);
-}
-
-DotCallGraph::~DotCallGraph()
-{
- deleteNodes(m_startNode);
- delete m_usedNodes;
-}
-
-QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat graphFormat,
- EmbeddedOutputFormat textFormat,
- const char *path,const char *fileName,
- const char *relPath,bool generateImageMap,int
- graphId) const
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
- static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
-
- QCString baseName = m_diskName + (m_inverse ? "_icgraph" : "_cgraph");
- QCString mapName = baseName;
-
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString absBaseName = d.absPath().utf8()+"/"+baseName;
- QCString absDotName = absBaseName+".dot";
- QCString absMapName = absBaseName+".map";
- QCString absPdfName = absBaseName+".pdf";
- QCString absEpsName = absBaseName+".eps";
- QCString absImgName = absBaseName+"."+imgExt;
-
- bool regenerate = FALSE;
-
- if (updateDotGraph(m_startNode,
- DotNode::CallGraph,
- absBaseName,
- graphFormat,
- m_inverse ? "RL" : "LR", // lrRank
- FALSE, // renderParents
- m_inverse, // backArrows
- m_startNode->label()
- ) ||
- !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
- usePDFLatex ? absPdfName : absEpsName,
- graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString())
- )
- {
- regenerate=TRUE;
- if (graphFormat==GOF_BITMAP)
- {
- // run dot to create a bitmap image
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
-
- }
- else if (graphFormat==GOF_EPS)
- {
- // run dot to create a .eps image
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- if (usePDFLatex)
- {
- dotRun->addJob("pdf",absPdfName,absBaseName);
- }
- else
- {
- dotRun->addJob("ps",absEpsName);
- }
- DotManager::instance()->addRun(dotRun);
-
- }
- }
- Doxygen::indexList->addImageFile(baseName+"."+imgExt);
-
- if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
- {
- out << "<para>" << endl;
- out << " <informalfigure>" << endl;
- out << " <mediaobject>" << endl;
- out << " <imageobject>" << endl;
- out << " <imagedata";
- out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
- out << "</imagedata>" << endl;
- out << " </imageobject>" << endl;
- out << " </mediaobject>" << endl;
- out << " </informalfigure>" << endl;
- out << "</para>" << endl;
- }
- else if (graphFormat==GOF_BITMAP && generateImageMap)
- {
- 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(),TRUE,graphId);
- }
- 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 (graphFormat==GOF_EPS) // encapsulated postscript
- {
- if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
- {
- int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
- out << endl << "% FIG " << figId << endl;
- }
- }
- if (!regenerate) removeDotGraph(absDotName);
-
- return baseName;
-}
-
-bool DotCallGraph::isTrivial() const
-{
- return m_startNode->m_children==0;
-}
-
-bool DotCallGraph::isTooBig() const
-{
- static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
- int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0;
- return numNodes>=maxNodes;
-}
-
-//-------------------------------------------------------------
-static void writeDotDirDepGraph(FTextStream &t,DirDef *dd,bool linkRelations);
-
-DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir)
-{
-}
-
-DotDirDeps::~DotDirDeps()
-{
-}
-
-QCString DotDirDeps::writeGraph(FTextStream &out,
- GraphOutputFormat graphFormat,
- EmbeddedOutputFormat textFormat,
- const char *path,
- const char *fileName,
- const char *relPath,
- bool generateImageMap,
- int graphId,
- bool linkRelations) const
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
- static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
-
- QCString baseName=m_dir->getOutputFileBase()+"_dep";
- QCString mapName=escapeCharsInString(baseName,FALSE);
-
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString absBaseName = d.absPath().utf8()+"/"+baseName;
- QCString absDotName = absBaseName+".dot";
- QCString absMapName = absBaseName+".map";
- QCString absPdfName = absBaseName+".pdf";
- QCString absEpsName = absBaseName+".eps";
- QCString absImgName = absBaseName+"."+imgExt;
-
- // compute md5 checksum of the graph were are about to generate
- QGString theGraph;
- FTextStream md5stream(&theGraph);
- //m_dir->writeDepGraph(md5stream);
- writeDotDirDepGraph(md5stream,m_dir,linkRelations);
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.rawData(),33);
- bool regenerate=FALSE;
- if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
- !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
- usePDFLatex ? absPdfName : absEpsName,
- graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString())
- )
- {
- regenerate=TRUE;
-
- QFile f(absDotName);
- if (!f.open(IO_WriteOnly))
- {
- err("Cannot create file %s.dot for writing!\n",baseName.data());
- }
- FTextStream t(&f);
- t << theGraph.data();
- f.close();
-
- if (graphFormat==GOF_BITMAP)
- {
- // run dot to create a bitmap image
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
- }
- else if (graphFormat==GOF_EPS)
- {
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- if (usePDFLatex)
- {
- dotRun->addJob("pdf",absPdfName,absBaseName);
- }
- else
- {
- dotRun->addJob("ps",absEpsName);
- }
- DotManager::instance()->addRun(dotRun);
- }
- }
- Doxygen::indexList->addImageFile(baseName+"."+imgExt);
-
- if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
- {
- out << "<para>" << endl;
- out << " <informalfigure>" << endl;
- out << " <mediaobject>" << endl;
- out << " <imageobject>" << endl;
- out << " <imagedata";
- out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
- out << "</imagedata>" << endl;
- out << " </imageobject>" << endl;
- out << " </mediaobject>" << endl;
- out << " </informalfigure>" << endl;
- out << "</para>" << endl;
- }
- else if (graphFormat==GOF_BITMAP && generateImageMap)
- {
- 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(),TRUE,graphId);
- }
- 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 (graphFormat==GOF_EPS)
- {
- if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName))
- {
- int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
- out << endl << "% FIG " << figId << endl;
- }
- }
- if (!regenerate) removeDotGraph(absDotName);
-
- return baseName;
-}
-
-bool DotDirDeps::isTrivial() const
-{
- return m_dir->depGraphIsTrivial();
-}
-
-//-------------------------------------------------------------
+ friend void generateGraphLegend(const char* path);
+};
void generateGraphLegend(const char *path)
{
QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
-
- QGString theGraph;
- FTextStream md5stream(&theGraph);
- writeGraphHeader(md5stream,theTranslator->trLegendTitle());
- md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n";
- md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"grey75\"];\n";
- md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n";
- md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << FONTNAME << "\"];\n";
- md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n";
- writeGraphFooter(md5stream);
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.rawData(),33);
- QCString absBaseName = (QCString)path+"/graph_legend";
- QCString absDotName = absBaseName+".dot";
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString imgName = "graph_legend."+imgExt;
- QCString absImgName = absBaseName+"."+imgExt;
- if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
- !checkDeliverables(absImgName))
- {
- QFile dotFile(absDotName);
- if (!dotFile.open(IO_WriteOnly))
- {
- err("Could not open file %s for writing\n",dotFile.name().data());
- return;
- }
-
- FTextStream dotText(&dotFile);
- dotText << theGraph;
- dotFile.close();
-
- // run dot to generate the a bitmap image from the graph
+ GraphLegendDotGraph dg;
+ FTextStream ts;
+ dg.writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0);
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName);
- dotRun->addJob(imgFmt,absImgName);
- DotManager::instance()->addRun(dotRun);
- }
- else
- {
- removeDotGraph(absDotName);
- }
- Doxygen::indexList->addImageFile(imgName);
-
- if (imgExt=="svg")
+ if (getDotImageExtension()=="svg")
{
DotManager::instance()->addSVGObject(
- absBaseName+Config_getString(HTML_FILE_EXTENSION),
+ dg.absBaseName()+Config_getString(HTML_FILE_EXTENSION),
"graph_legend",
- absImgName,QCString());
+ dg.absImgName(),QCString());
}
}
@@ -4256,19 +493,20 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir,
}
QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
QCString imgName = (QCString)outFile+"."+imgExt;
QCString absImgName = d.absPath().utf8()+"/"+imgName;
QCString absOutFile = d.absPath().utf8()+"/"+outFile;
- DotRunner dotRun(inFile,d.absPath().data(),FALSE,absImgName);
+ DotRunner dotRun(inFile, QCString());
if (format==GOF_BITMAP)
- dotRun.addJob(imgFmt,absImgName);
+ {
+ dotRun.addJob(Config_getEnum(DOT_IMAGE_FORMAT),absImgName);
+ }
else // format==GOF_EPS
{
if (Config_getBool(USE_PDFLATEX))
{
- dotRun.addJob("pdf",absOutFile+".pdf",absOutFile);
+ dotRun.addJob("pdf",absOutFile+".pdf");
}
else
{
@@ -4282,13 +520,10 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir,
return;
}
- if (format==GOF_BITMAP) checkDotResult(getDotImageExtension(),absImgName);
-
Doxygen::indexList->addImageFile(imgName);
}
-
/*! Writes user defined image map to the output.
* \param t text stream to write to
* \param inFile just the basename part of the filename
@@ -4312,11 +547,10 @@ void writeDotImageMapFromFile(FTextStream &t,
QCString mapName = baseName+".map";
QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
QCString imgName = baseName+"."+imgExt;
QCString absOutFile = d.absPath().utf8()+"/"+mapName;
- DotRunner dotRun(inFile,d.absPath().data(),FALSE);
+ DotRunner dotRun(inFile, QCString());
dotRun.addJob(MAP_CMD,absOutFile);
dotRun.preventCleanUp();
if (!dotRun.run())
@@ -4331,7 +565,7 @@ void writeDotImageMapFromFile(FTextStream &t,
QCString svgName=outDir+"/"+baseName+".svg";
writeSVGFigureLink(t,relPath,baseName,svgName);
DotFilePatcher patcher(svgName);
- patcher.addSVGConversion(relPath,TRUE,context,TRUE,graphId);
+ patcher.addSVGConversion("",TRUE,context,TRUE,graphId);
patcher.run();
}
else // bitmap graphics
@@ -4351,628 +585,3 @@ void writeDotImageMapFromFile(FTextStream &t,
}
d.remove(absOutFile);
}
-
-//-------------------------------------------------------------
-
-int DotGroupCollaboration::m_curNodeNumber = 0;
-
-void DotGroupCollaboration::resetNumbering()
-{
- m_curNodeNumber = 0;
-}
-
-DotGroupCollaboration::DotGroupCollaboration(GroupDef* gd)
-{
- QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase();
- m_usedNodes = new QDict<DotNode>(1009);
- QCString tooltip = gd->briefDescriptionAsTooltip();
- m_rootNode = new DotNode(m_curNodeNumber++, gd->groupTitle(), tooltip, tmp_url, TRUE );
- m_rootNode->markAsVisible();
- m_usedNodes->insert(gd->name(), m_rootNode );
- m_edges.setAutoDelete(TRUE);
-
- m_diskName = gd->getOutputFileBase();
-
- buildGraph( gd );
-}
-
-DotGroupCollaboration::~DotGroupCollaboration()
-{
- delete m_usedNodes;
-}
-
-void DotGroupCollaboration::buildGraph(GroupDef* gd)
-{
- QCString tmp_url;
- //===========================
- // hierarchy.
-
- // Write parents
- GroupList *groups = gd->partOfGroups();
- if ( groups )
- {
- GroupListIterator gli(*groups);
- GroupDef *d;
- for (gli.toFirst();(d=gli.current());++gli)
- {
- DotNode* nnode = m_usedNodes->find(d->name());
- if ( !nnode )
- { // add node
- tmp_url = d->getReference()+"$"+d->getOutputFileBase();
- QCString tooltip = d->briefDescriptionAsTooltip();
- nnode = new DotNode(m_curNodeNumber++, d->groupTitle(), tooltip, tmp_url );
- nnode->markAsVisible();
- m_usedNodes->insert(d->name(), nnode );
- }
- tmp_url = "";
- addEdge( nnode, m_rootNode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
- }
- }
-
- // Add subgroups
- if ( gd->getSubGroups() && gd->getSubGroups()->count() )
- {
- QListIterator<GroupDef> defli(*gd->getSubGroups());
- GroupDef *def;
- for (;(def=defli.current());++defli)
- {
- DotNode* nnode = m_usedNodes->find(def->name());
- if ( !nnode )
- { // add node
- tmp_url = def->getReference()+"$"+def->getOutputFileBase();
- QCString tooltip = def->briefDescriptionAsTooltip();
- nnode = new DotNode(m_curNodeNumber++, def->groupTitle(), tooltip, tmp_url );
- nnode->markAsVisible();
- m_usedNodes->insert(def->name(), nnode );
- }
- tmp_url = "";
- addEdge( m_rootNode, nnode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
- }
- }
-
- //=======================
- // Write collaboration
-
- // Add members
- addMemberList( gd->getMemberList(MemberListType_allMembersList) );
-
- // Add classes
- if ( gd->getClasses() && gd->getClasses()->count() )
- {
- ClassSDict::Iterator defli(*gd->getClasses());
- ClassDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- if (!def->anchor().isEmpty())
- {
- tmp_url+="#"+def->anchor();
- }
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass );
- }
- }
-
- // Add namespaces
- if ( gd->getNamespaces() && gd->getNamespaces()->count() )
- {
- NamespaceSDict::Iterator defli(*gd->getNamespaces());
- NamespaceDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace );
- }
- }
-
- // Add files
- if ( gd->getFiles() && gd->getFiles()->count() )
- {
- QListIterator<FileDef> defli(*gd->getFiles());
- FileDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile );
- }
- }
-
- // Add pages
- if ( gd->getPages() && gd->getPages()->count() )
- {
- PageSDict::Iterator defli(*gd->getPages());
- PageDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages );
- }
- }
-
- // Add directories
- if ( gd->getDirs() && gd->getDirs()->count() )
- {
- QListIterator<DirDef> defli(*gd->getDirs());
- DirDef *def;
- for (;(def=defli.current());++defli)
- {
- tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir );
- }
- }
-}
-
-void DotGroupCollaboration::addMemberList( MemberList* ml )
-{
- if ( !( ml && ml->count()) ) return;
- MemberListIterator defli(*ml);
- MemberDef *def;
- for (;(def=defli.current());++defli)
- {
- QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension
- +"#"+def->anchor();
- addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember );
- }
-}
-
-DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge(
- DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
- const QCString& _label, const QCString& _url )
-{
- // search a existing link.
- QListIterator<Edge> lli(m_edges);
- Edge* newEdge = 0;
- for ( lli.toFirst(); (newEdge=lli.current()); ++lli)
- {
- if ( newEdge->pNStart==_pNStart &&
- newEdge->pNEnd==_pNEnd &&
- newEdge->eType==_eType
- )
- { // edge already found
- break;
- }
- }
- if ( newEdge==0 ) // new link
- {
- newEdge = new Edge(_pNStart,_pNEnd,_eType);
- m_edges.append( newEdge );
- }
-
- if (!_label.isEmpty())
- {
- newEdge->links.append(new Link(_label,_url));
- }
-
- return newEdge;
-}
-
-void DotGroupCollaboration::addCollaborationMember(
- Definition* def, QCString& url, EdgeType eType )
-{
- // Create group nodes
- if ( !def->partOfGroups() )
- return;
- GroupListIterator gli(*def->partOfGroups());
- GroupDef *d;
- QCString tmp_str;
- for (;(d=gli.current());++gli)
- {
- DotNode* nnode = m_usedNodes->find(d->name());
- if ( nnode != m_rootNode )
- {
- if ( nnode==0 )
- { // add node
- tmp_str = d->getReference()+"$"+d->getOutputFileBase();
- QCString tooltip = d->briefDescriptionAsTooltip();
- nnode = new DotNode(m_curNodeNumber++, d->groupTitle(), tooltip, tmp_str );
- nnode->markAsVisible();
- m_usedNodes->insert(d->name(), nnode );
- }
- tmp_str = def->qualifiedName();
- addEdge( m_rootNode, nnode, eType, tmp_str, url );
- }
- }
-}
-
-
-QCString DotGroupCollaboration::writeGraph( FTextStream &t,
- GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat,
- const char *path, const char *fileName, const char *relPath,
- bool writeImageMap,int graphId) const
-{
- QDir d(path);
- // store the original directory
- if (!d.exists())
- {
- err("Output dir %s does not exist!\n",path); exit(1);
- }
- static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
-
- QGString theGraph;
- FTextStream md5stream(&theGraph);
- writeGraphHeader(md5stream,m_rootNode->label());
-
- // clean write flags
- QDictIterator<DotNode> dni(*m_usedNodes);
- DotNode *pn;
- for (dni.toFirst();(pn=dni.current());++dni)
- {
- pn->clearWriteFlag();
- }
-
- // write other nodes.
- for (dni.toFirst();(pn=dni.current());++dni)
- {
- pn->write(md5stream,DotNode::Inheritance,graphFormat,TRUE,FALSE,FALSE);
- }
-
- // write edges
- QListIterator<Edge> eli(m_edges);
- Edge* edge;
- for (eli.toFirst();(edge=eli.current());++eli)
- {
- edge->write( md5stream );
- }
-
- writeGraphFooter(md5stream);
- uchar md5_sig[16];
- QCString sigStr(33);
- MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig);
- MD5SigToString(md5_sig,sigStr.rawData(),33);
- QCString imgExt = getDotImageExtension();
- QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT);
- QCString baseName = m_diskName;
- QCString imgName = baseName+"."+imgExt;
- QCString absPath = d.absPath().data();
- QCString absBaseName = absPath+"/"+baseName;
- QCString absDotName = absBaseName+".dot";
- QCString absImgName = absBaseName+"."+imgExt;
- QCString absMapName = absBaseName+".map";
- QCString absPdfName = absBaseName+".pdf";
- QCString absEpsName = absBaseName+".eps";
- bool regenerate=FALSE;
- if (checkAndUpdateMd5Signature(absBaseName,sigStr) ||
- !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName :
- usePDFLatex ? absPdfName : absEpsName,
- graphFormat==GOF_BITMAP /*&& generateImageMap*/ ? absMapName : QCString())
- )
- {
- regenerate=TRUE;
-
- QFile dotfile(absDotName);
- if (dotfile.open(IO_WriteOnly))
- {
- FTextStream tdot(&dotfile);
- tdot << theGraph;
- dotfile.close();
- }
-
- if (graphFormat==GOF_BITMAP) // run dot to create a bitmap image
- {
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- dotRun->addJob(imgFmt,absImgName);
- if (writeImageMap) dotRun->addJob(MAP_CMD,absMapName);
- DotManager::instance()->addRun(dotRun);
-
- }
- else if (graphFormat==GOF_EPS)
- {
- DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE);
- if (usePDFLatex)
- {
- dotRun->addJob("pdf",absPdfName,absBaseName);
- }
- else
- {
- dotRun->addJob("ps",absEpsName);
- }
- DotManager::instance()->addRun(dotRun);
- }
-
- }
- if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook)
- {
- t << "<para>" << endl;
- t << " <informalfigure>" << endl;
- t << " <mediaobject>" << endl;
- t << " <imageobject>" << endl;
- t << " <imagedata";
- t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">";
- t << "</imagedata>" << endl;
- t << " </imageobject>" << endl;
- t << " </mediaobject>" << endl;
- t << " </informalfigure>" << endl;
- t << "</para>" << endl;
- }
- else if (graphFormat==GOF_BITMAP && writeImageMap)
- {
- QCString mapLabel = escapeCharsInString(baseName,FALSE);
- 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(),TRUE,graphId);
- }
- 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;
- }
- else if (graphFormat==GOF_EPS)
- {
- if (regenerate || !writeVecGfxFigure(t,baseName,absBaseName))
- {
- int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE);
- t << endl << "% FIG " << figId << endl;
- }
- }
- if (!regenerate) removeDotGraph(absDotName);
-
- return baseName;
-}
-
-void DotGroupCollaboration::Edge::write( FTextStream &t ) const
-{
- const char* linkTypeColor[] = {
- "darkorchid3"
- ,"orange"
- ,"blueviolet"
- ,"darkgreen"
- ,"firebrick4"
- ,"grey75"
- ,"midnightblue"
- };
- QCString arrowStyle = "dir=\"none\", style=\"dashed\"";
- t << " Node" << pNStart->number();
- t << "->";
- t << "Node" << pNEnd->number();
-
- t << " [shape=plaintext";
- if (links.count()>0) // there are links
- {
- t << ", ";
- // HTML-like edge labels crash on my Mac with Graphviz 2.0! and
- // are not supported by older version of dot.
- //
- //t << label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">";
- //QListIterator<Link> lli(links);
- //Link *link;
- //for( lli.toFirst(); (link=lli.current()); ++lli)
- //{
- // t << "<TR><TD";
- // if ( !link->url.isEmpty() )
- // t << " HREF=\"" << link->url << "\"";
- // t << ">" << link->label << "</TD></TR>";
- //}
- //t << "</TABLE>>";
-
- t << "label=\"";
- QListIterator<Link> lli(links);
- Link *link;
- bool first=TRUE;
- int count=0;
- const int maxLabels = 10;
- for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count)
- {
- if (first) first=FALSE; else t << "\\n";
- t << convertLabel(link->label);
- }
- if (count==maxLabels) t << "\\n...";
- t << "\"";
-
- }
- switch( eType )
- {
- case thierarchy:
- arrowStyle = "dir=\"back\", style=\"solid\"";
- break;
- default:
- t << ", color=\"" << linkTypeColor[(int)eType] << "\"";
- break;
- }
- t << ", " << arrowStyle;
- t << "];" << endl;
-}
-
-bool DotGroupCollaboration::isTrivial() const
-{
- return m_usedNodes->count() <= 1;
-}
-
-void DotGroupCollaboration::writeGraphHeader(FTextStream &t,
- const QCString &title) const
-{
- t << "digraph ";
- if (title.isEmpty())
- {
- t << "\"Dot Graph\"";
- }
- else
- {
- t << "\"" << convertToXML(title) << "\"";
- }
- t << endl;
- t << "{" << endl;
- if (Config_getBool(DOT_TRANSPARENT))
- {
- t << " bgcolor=\"transparent\";" << endl;
- }
- t << " edge [fontname=\"" << FONTNAME << "\",fontsize=\"" << FONTSIZE << "\","
- "labelfontname=\"" << FONTNAME << "\",labelfontsize=\"" << FONTSIZE << "\"];\n";
- t << " node [fontname=\"" << FONTNAME << "\",fontsize=\"" << FONTSIZE << "\",shape=box];\n";
- t << " rankdir=LR;\n";
-}
-
-void writeDotDirDepGraph(FTextStream &t,DirDef *dd,bool linkRelations)
-{
- t << "digraph \"" << dd->displayName() << "\" {\n";
- if (Config_getBool(DOT_TRANSPARENT))
- {
- t << " bgcolor=transparent;\n";
- }
- t << " compound=true\n";
- t << " node [ fontsize=\"" << FONTSIZE << "\", fontname=\"" << FONTNAME << "\"];\n";
- t << " edge [ labelfontsize=\"" << FONTSIZE << "\", labelfontname=\"" << FONTNAME << "\"];\n";
-
- QDict<DirDef> dirsInGraph(257);
-
- dirsInGraph.insert(dd->getOutputFileBase(),dd);
- if (dd->parent())
- {
- t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n";
- t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\""
- << dd->parent()->shortName()
- << "\" fontname=\"" << FONTNAME << "\", fontsize=\"" << FONTSIZE << "\", URL=\"";
- t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension;
- t << "\"]\n";
- }
- if (dd->isCluster())
- {
- t << " subgraph cluster" << dd->getOutputFileBase() << " {\n";
- t << " graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\""
- << " URL=\"" << dd->getOutputFileBase() << Doxygen::htmlFileExtension
- << "\"];\n";
- t << " " << dd->getOutputFileBase() << " [shape=plaintext label=\""
- << dd->shortName() << "\"];\n";
-
- // add nodes for sub directories
- QListIterator<DirDef> sdi(dd->subDirs());
- DirDef *sdir;
- for (sdi.toFirst();(sdir=sdi.current());++sdi)
- {
- t << " " << sdir->getOutputFileBase() << " [shape=box label=\""
- << sdir->shortName() << "\"";
- if (sdir->isCluster())
- {
- t << " color=\"red\"";
- }
- else
- {
- t << " color=\"black\"";
- }
- t << " fillcolor=\"white\" style=\"filled\"";
- t << " URL=\"" << sdir->getOutputFileBase()
- << Doxygen::htmlFileExtension << "\"";
- t << "];\n";
- dirsInGraph.insert(sdir->getOutputFileBase(),sdir);
- }
- t << " }\n";
- }
- else
- {
- t << " " << dd->getOutputFileBase() << " [shape=box, label=\""
- << dd->shortName() << "\", style=\"filled\", fillcolor=\"#eeeeff\","
- << " pencolor=\"black\", URL=\"" << dd->getOutputFileBase()
- << Doxygen::htmlFileExtension << "\"];\n";
- }
- if (dd->parent())
- {
- t << " }\n";
- }
-
- // add nodes for other used directories
- QDictIterator<UsedDir> udi(*dd->usedDirs());
- UsedDir *udir;
- //printf("*** For dir %s\n",shortName().data());
- for (udi.toFirst();(udir=udi.current());++udi)
- // for each used dir (=directly used or a parent of a directly used dir)
- {
- const DirDef *usedDir=udir->dir();
- DirDef *dir=dd;
- while (dir)
- {
- //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n",
- // dir->shortName().data(),usedDir->shortName().data(),
- // dir->parent()==usedDir->parent(),
- // usedDir->shortName().data(),
- // shortName().data(),
- // !usedDir->isParentOf(this)
- // );
- if (dir!=usedDir && dir->parent()==usedDir->parent() &&
- !usedDir->isParentOf(dd))
- // include if both have the same parent (or no parent)
- {
- t << " " << usedDir->getOutputFileBase() << " [shape=box label=\""
- << usedDir->shortName() << "\"";
- if (usedDir->isCluster())
- {
- if (!Config_getBool(DOT_TRANSPARENT))
- {
- t << " fillcolor=\"white\" style=\"filled\"";
- }
- t << " color=\"red\"";
- }
- t << " URL=\"" << usedDir->getOutputFileBase()
- << Doxygen::htmlFileExtension << "\"];\n";
- dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir);
- break;
- }
- dir=dir->parent();
- }
- }
-
- // add relations between all selected directories
- DirDef *dir;
- QDictIterator<DirDef> di(dirsInGraph);
- for (di.toFirst();(dir=di.current());++di) // foreach dir in the graph
- {
- QDictIterator<UsedDir> udi(*dir->usedDirs());
- UsedDir *udir;
- for (udi.toFirst();(udir=udi.current());++udi) // foreach used dir
- {
- const DirDef *usedDir=udir->dir();
- if ((dir!=dd || !udir->inherited()) && // only show direct dependendies for this dir
- (usedDir!=dd || !udir->inherited()) && // only show direct dependendies for this dir
- !usedDir->isParentOf(dir) && // don't point to own parent
- dirsInGraph.find(usedDir->getOutputFileBase())) // only point to nodes that are in the graph
- {
- QCString relationName;
- relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount());
- if (Doxygen::dirRelations.find(relationName)==0)
- {
- // new relation
- Doxygen::dirRelations.append(relationName,
- new DirRelation(relationName,dir,udir));
- }
- int nrefs = udir->filePairs().count();
- t << " " << dir->getOutputFileBase() << "->"
- << usedDir->getOutputFileBase();
- t << " [headlabel=\"" << nrefs << "\", labeldistance=1.5";
- if (linkRelations)
- {
- t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\"";
- }
- t << "];\n";
- }
- }
- }
-
- t << "}\n";
-}
-
-void resetDotNodeNumbering()
-{
- DotClassGraph::resetNumbering();
- DotInclDepGraph::resetNumbering();
- DotCallGraph::resetNumbering();
- DotGroupCollaboration::resetNumbering();
-}
-
diff --git a/src/dot.h b/src/dot.h
index dc77789..124a32b 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -1,13 +1,10 @@
/******************************************************************************
*
- *
- *
- *
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
+ * Copyright (C) 1997-2019 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
+ * 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.
*
@@ -16,8 +13,8 @@
*
*/
-#ifndef _DOT_H
-#define _DOT_H
+#ifndef DOT_H
+#define DOT_H
#include <qlist.h>
#include <qdict.h>
@@ -26,466 +23,24 @@
#include <qqueue.h>
#include <qthread.h>
#include "sortdict.h"
-#include "classdef.h"
+#include "qgstring.h"
+#include "qdir.h"
+#include "qcstring.h"
+#include "dotgraph.h"
+#include "dotfilepatcher.h"
+#include "dotrunner.h"
-class FileDef;
class FTextStream;
-class DotNodeList;
-class ClassSDict;
-class MemberDef;
-class Definition;
-class DirDef;
-class GroupDef;
-class DotGroupCollaboration;
+class DotRunner;
class DotRunnerQueue;
-
-enum GraphOutputFormat { GOF_BITMAP, GOF_EPS };
-enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook };
-
-// the graphicx LaTeX has a limitation of maximum size of 16384
-// To be on the save side we take it a little bit smaller i.e. 150 inch * 72 dpi
-// It is anyway hard to view these size of images
-#define MAX_LATEX_GRAPH_INCH 150
-#define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72)
-
-/** Attributes of an edge of a dot graph */
-struct EdgeInfo
-{
- enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5, Orange2=6 };
- enum Styles { Solid=0, Dashed=1 };
- EdgeInfo() : m_color(0), m_style(0), m_labColor(0) {}
- ~EdgeInfo() {}
- int m_color;
- int m_style;
- QCString m_label;
- QCString m_url;
- int m_labColor;
-};
-
-/** A node in a dot graph */
-class DotNode
-{
- public:
- enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph };
- enum TruncState { Unknown, Truncated, Untruncated };
- DotNode(int n,const char *lab,const char *tip,const char *url,
- bool rootNode=FALSE,ClassDef *cd=0);
- ~DotNode();
- void addChild(DotNode *n,
- int edgeColor=EdgeInfo::Purple,
- int edgeStyle=EdgeInfo::Solid,
- const char *edgeLab=0,
- const char *edgeURL=0,
- int edgeLabCol=-1
- );
- void addParent(DotNode *n);
- void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0);
- void removeChild(DotNode *n);
- void removeParent(DotNode *n);
- int findParent( DotNode *n );
- void write(FTextStream &t,GraphType gt,GraphOutputFormat f,
- bool topDown,bool toChildren,bool backArrows);
- int m_subgraphId;
- void clearWriteFlag();
- void writeXML(FTextStream &t,bool isClassGraph);
- void writeDocbook(FTextStream &t,bool isClassGraph);
- void writeDEF(FTextStream &t);
- QCString label() const { return m_label; }
- int number() const { return m_number; }
- bool isVisible() const { return m_visible; }
- TruncState isTruncated() const { return m_truncated; }
- int distance() const { return m_distance; }
- void renumberNodes(int &number);
-
- private:
- void colorConnectedNodes(int curColor);
- void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f,
- bool hasNonReachableChildren);
- void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn,
- EdgeInfo *ei,bool topDown, bool pointBack=TRUE);
- void setDistance(int distance);
- const DotNode *findDocNode() const; // only works for acyclic graphs!
- void markAsVisible(bool b=TRUE) { m_visible=b; }
- void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; }
- int m_number;
- QCString m_label; //!< label text
- QCString m_tooltip; //!< node's tooltip
- QCString m_url; //!< url of the node (format: remote$local)
- QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows)
- QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows)
- QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child
- bool m_deleted; //!< used to mark a node as deleted
- bool m_written; //!< used to mark a node as written
- bool m_hasDoc; //!< used to mark a node as documented
- bool m_isRoot; //!< indicates if this is a root node
- ClassDef * m_classDef; //!< class representing this node (can be 0)
- bool m_visible; //!< is the node visible in the output
- TruncState m_truncated; //!< does the node have non-visible children/parents
- int m_distance; //!< shortest path to the root node
- bool m_renumbered;//!< indicates if the node has been renumbered (to prevent endless loops)
-
- friend class DotGfxHierarchyTable;
- friend class DotClassGraph;
- friend class DotInclDepGraph;
- friend class DotNodeList;
- friend class DotCallGraph;
- friend class DotGroupCollaboration;
- friend class DotInheritanceGraph;
-
- friend QCString computeMd5Signature(
- DotNode *root, GraphType gt,
- GraphOutputFormat f,
- const QCString &rank,
- bool renderParents,
- bool backArrows,
- const QCString &title,
- QCString &graphStr
- );
-};
-
-/** Class representing a list of DotNode objects. */
-class DotNodeList : public QList<DotNode>
-{
- public:
- DotNodeList() : QList<DotNode>() {}
- ~DotNodeList() {}
- private:
- int compareValues(const DotNode *n1,const DotNode *n2) const;
-};
-
-/** Represents a graphical class hierarchy */
-class DotGfxHierarchyTable
-{
- public:
- DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class);
- ~DotGfxHierarchyTable();
- void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
- void createGraph(DotNode *rootNode,FTextStream &t,const char *path,const char *fileName,int id) const;
- const DotNodeList *subGraphs() const { return m_rootSubgraphs; }
-
- private:
- void addHierarchy(DotNode *n,ClassDef *cd,bool hide);
- void addClassList(ClassSDict *cl);
-
- QCString m_prefix;
- ClassDef::CompoundType m_classType;
- QList<DotNode> *m_rootNodes;
- QDict<DotNode> *m_usedNodes;
- int m_curNodeNumber;
- DotNodeList *m_rootSubgraphs;
-};
-
-/** Representation of a class inheritance or dependency graph */
-class DotClassGraph
-{
- public:
- DotClassGraph(ClassDef *cd,DotNode::GraphType t);
- ~DotClassGraph();
- bool isTrivial() const;
- bool isTooBig() const;
- QCString writeGraph(FTextStream &t,GraphOutputFormat gf,EmbeddedOutputFormat ef,
- const char *path, const char *fileName, const char *relPath,
- bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1) const;
-
- void writeXML(FTextStream &t);
- void writeDocbook(FTextStream &t);
- void writeDEF(FTextStream &t);
- static void resetNumbering();
-
- private:
- void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance);
- bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents);
- void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents);
- void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,
- const char *usedName,const char *templSpec,
- bool base,int distance);
-
- DotNode * m_startNode;
- QDict<DotNode> * m_usedNodes;
- static int m_curNodeNumber;
- DotNode::GraphType m_graphType;
- QCString m_collabFileName;
- QCString m_inheritFileName;
- bool m_lrRank;
-};
-
-/** Representation of an include dependency graph */
-class DotInclDepGraph
-{
- public:
- DotInclDepGraph(FileDef *fd,bool inverse);
- ~DotInclDepGraph();
- QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
- const char *path,const char *fileName,const char *relPath,
- bool writeImageMap=TRUE,int graphId=-1) const;
- bool isTrivial() const;
- bool isTooBig() const;
- QCString diskName() const;
- void writeXML(FTextStream &t);
- void writeDocbook(FTextStream &t);
- static void resetNumbering();
-
- private:
- void buildGraph(DotNode *n,FileDef *fd,int distance);
- void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes);
- void determineTruncatedNodes(QList<DotNode> &queue);
-
- DotNode *m_startNode;
- QDict<DotNode> *m_usedNodes;
- static int m_curNodeNumber;
- QCString m_inclDepFileName;
- QCString m_inclByDepFileName;
- bool m_inverse;
-};
-
-/** Representation of an call graph */
-class DotCallGraph
-{
- public:
- DotCallGraph(MemberDef *md,bool inverse);
- ~DotCallGraph();
- QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
- const char *path,const char *fileName,
- const char *relPath,bool writeImageMap=TRUE,
- int graphId=-1) const;
- void buildGraph(DotNode *n,MemberDef *md,int distance);
- bool isTrivial() const;
- bool isTooBig() const;
- void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes);
- void determineTruncatedNodes(QList<DotNode> &queue);
- static void resetNumbering();
-
- private:
- DotNode *m_startNode;
- static int m_curNodeNumber;
- QDict<DotNode> *m_usedNodes;
- bool m_inverse;
- QCString m_diskName;
- Definition * m_scope;
-};
-
-/** Representation of an directory dependency graph */
-class DotDirDeps
-{
- public:
- DotDirDeps(DirDef *dir);
- ~DotDirDeps();
- bool isTrivial() const;
- QCString writeGraph(FTextStream &out,
- GraphOutputFormat gf,
- EmbeddedOutputFormat ef,
- const char *path,
- const char *fileName,
- const char *relPath,
- bool writeImageMap=TRUE,
- int graphId=-1,
- bool linkRelations=TRUE) const;
- private:
- DirDef *m_dir;
-};
-
-/** Representation of a group collaboration graph */
-class DotGroupCollaboration
-{
- public :
- enum EdgeType
- { tmember = 0,
- tclass,
- tnamespace,
- tfile,
- tpages,
- tdir,
- thierarchy
- };
-
- class Link
- {
- public:
- Link(const QCString lab,const QCString &u) : label(lab), url(u) {}
- QCString label;
- QCString url;
- };
-
- class Edge
- {
- public :
- Edge(DotNode *start,DotNode *end,EdgeType type)
- : pNStart(start), pNEnd(end), eType(type)
- { links.setAutoDelete(TRUE); }
-
- DotNode* pNStart;
- DotNode* pNEnd;
- EdgeType eType;
-
- QList<Link> links;
- void write( FTextStream &t ) const;
- };
-
- DotGroupCollaboration(GroupDef* gd);
- ~DotGroupCollaboration();
- QCString writeGraph(FTextStream &t, GraphOutputFormat gf,EmbeddedOutputFormat ef,
- const char *path,const char *fileName,const char *relPath,
- bool writeImageMap=TRUE,int graphId=-1) const;
- void buildGraph(GroupDef* gd);
- bool isTrivial() const;
- static void resetNumbering();
-
- private :
- void addCollaborationMember( Definition* def, QCString& url, EdgeType eType );
- void addMemberList( class MemberList* ml );
- void writeGraphHeader(FTextStream &t,const QCString &title) const;
- Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
- const QCString& _label, const QCString& _url );
-
- DotNode *m_rootNode;
- static int m_curNodeNumber;
- QDict<DotNode> *m_usedNodes;
- QCString m_diskName;
- QList<Edge> m_edges;
-};
-
-/** Minimal constant string class that is thread safe, once initialized. */
-class DotConstString
-{
- public:
- DotConstString() { m_str=0; m_pdfstr=0;}
- ~DotConstString() { delete[] m_str; delete[] m_pdfstr;}
- DotConstString(const QCString &s, const QCString &p = NULL) : m_str(0), m_pdfstr(0) { set(s); setpdf(p);}
- DotConstString(const DotConstString &s) : m_str(0), m_pdfstr(0) { set(s.data()); }
- const char *data() const { return m_str; }
- const char *pdfData() const { return m_pdfstr; }
- bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; }
- void set(const QCString &s)
- {
- delete[] m_str;
- m_str=0;
- if (!s.isEmpty())
- {
- m_str=new char[s.length()+1];
- qstrcpy(m_str,s.data());
- }
- }
- void setpdf(const QCString &p)
- {
- delete[] m_pdfstr;
- m_pdfstr=0;
- if (!p.isEmpty())
- {
- m_pdfstr=new char[p.length()+1];
- qstrcpy(m_pdfstr,p.data());
- }
- }
- private:
- DotConstString &operator=(const DotConstString &);
- char *m_str;
- char *m_pdfstr;
-};
-
-/** Helper class to run dot from doxygen.
- */
-class DotRunner
-{
- public:
- struct CleanupItem
- {
- DotConstString path;
- DotConstString file;
- };
-
- /** Creates a runner for a dot \a file. */
- DotRunner(const QCString &file,const QCString &fontPath,bool checkResult,
- const QCString &imageName = QCString());
-
- /** Adds an additional job to the run.
- * Performing multiple jobs one file can be faster.
- */
- void addJob(const char *format,const char *output, const char *base = NULL);
-
- void addPostProcessing(const char *cmd,const char *args);
-
- void preventCleanUp() { m_cleanUp = FALSE; }
-
- /** Runs dot for all jobs added. */
- bool run();
- const CleanupItem &cleanup() const { return m_cleanupItem; }
-
- private:
- DotConstString m_dotExe;
- bool m_multiTargets;
- QList<DotConstString> m_jobs;
- DotConstString m_postArgs;
- DotConstString m_postCmd;
- DotConstString m_file;
- DotConstString m_path;
- bool m_checkResult;
- DotConstString m_imageName;
- DotConstString m_imgExt;
- bool m_cleanUp;
- CleanupItem m_cleanupItem;
-};
-
-/** Helper class to insert a set of map file into an output file */
-class DotFilePatcher
-{
- public:
- struct Map
- {
- QCString mapFile;
- QCString relPath;
- bool urlOnly;
- QCString context;
- QCString label;
- bool zoomable;
- int graphId;
- };
- 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,bool zoomable,int graphId);
- int addSVGObject(const QCString &baseName, const QCString &figureName,
- const QCString &relPath);
- bool run();
- QCString file() const;
-
- private:
- QList<Map> m_maps;
- QCString m_patchFile;
-};
-
-/** Queue of dot jobs to run. */
-class DotRunnerQueue
-{
- public:
- void enqueue(DotRunner *runner);
- DotRunner *dequeue();
- uint count() const;
- private:
- QWaitCondition m_bufferNotEmpty;
- QQueue<DotRunner> m_queue;
- mutable QMutex m_mutex;
-};
-
-/** Worker thread to execute a dot run */
-class DotWorkerThread : public QThread
-{
- public:
- DotWorkerThread(DotRunnerQueue *queue);
- void run();
- void cleanup();
- private:
- DotRunnerQueue *m_queue;
- QList<DotRunner::CleanupItem> m_cleanupItems;
-};
+class DotWorkerThread;
/** Singleton that manages dot relation actions */
class DotManager
{
public:
static DotManager *instance();
- void addRun(DotRunner *run);
+ DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash);
int addMap(const QCString &file,const QCString &mapFile,
const QCString &relPath,bool urlOnly,
const QCString &context,const QCString &label);
@@ -500,13 +55,15 @@ class DotManager
private:
DotManager();
virtual ~DotManager();
- QList<DotRunner> m_dotRuns;
+
+ QDict<DotRunner> m_runners;
SDict<DotFilePatcher> m_dotMaps;
static DotManager *m_theInstance;
DotRunnerQueue *m_queue;
QList<DotWorkerThread> m_workers;
};
+void initDot();
/** Generated a graphs legend page */
void generateGraphLegend(const char *path);
@@ -517,7 +74,10 @@ void writeDotImageMapFromFile(FTextStream &t,
const QCString& inFile, const QCString& outDir,
const QCString& relPath,const QCString& baseName,
const QCString& context,int graphId=-1);
-
-void resetDotNodeNumbering();
+bool writeSVGFigureLink(FTextStream &out,const QCString &relPath,
+ const QCString &baseName,const QCString &absImgName);
+bool convertMapFile(FTextStream &t,const char *mapName,
+ const QCString relPath, bool urlOnly=FALSE,
+ const QCString &context=QCString());
#endif
diff --git a/src/dotcallgraph.cpp b/src/dotcallgraph.cpp
new file mode 100644
index 0000000..15d408a
--- /dev/null
+++ b/src/dotcallgraph.cpp
@@ -0,0 +1,217 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotcallgraph.h"
+
+#include "dotnode.h"
+#include "memberlist.h"
+#include "config.h"
+#include "util.h"
+
+#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES)
+#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES)
+#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH)
+
+void DotCallGraph::buildGraph(DotNode *n,const MemberDef *md,int distance)
+{
+ MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers();
+ if (refs)
+ {
+ refs->sort();
+ MemberSDict::Iterator mri(*refs);
+ MemberDef *rmd;
+ for (;(rmd=mri.current());++mri)
+ {
+ if (rmd->showInCallGraph())
+ {
+ QCString uniqueId;
+ uniqueId=rmd->getReference()+"$"+
+ rmd->getOutputFileBase()+"#"+rmd->anchor();
+ DotNode *bn = m_usedNodes->find(uniqueId);
+ if (bn) // file is already a node in the graph
+ {
+ n->addChild(bn,0,0,0);
+ bn->addParent(n);
+ bn->setDistance(distance);
+ }
+ else
+ {
+ QCString name;
+ if (HIDE_SCOPE_NAMES)
+ {
+ name = rmd->getOuterScope()==m_scope ?
+ rmd->name() : rmd->qualifiedName();
+ }
+ else
+ {
+ name = rmd->qualifiedName();
+ }
+ QCString tooltip = rmd->briefDescriptionAsTooltip();
+ bn = new DotNode(
+ getNextNodeNumber(),
+ linkToText(rmd->getLanguage(),name,FALSE),
+ tooltip,
+ uniqueId,
+ 0 //distance
+ );
+ n->addChild(bn,0,0,0);
+ bn->addParent(n);
+ bn->setDistance(distance);
+ m_usedNodes->insert(uniqueId,bn);
+
+ buildGraph(bn,rmd,distance+1);
+ }
+ }
+ }
+ }
+}
+
+void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes)
+{
+ while (queue.count()>0 && maxNodes>0)
+ {
+ DotNode *n = queue.take(0);
+ if (!n->isVisible() && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed
+ {
+ n->markAsVisible();
+ maxNodes--;
+ // add direct children
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ queue.append(dn);
+ }
+ }
+ }
+ }
+}
+
+void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue)
+{
+ while (queue.count()>0)
+ {
+ DotNode *n = queue.take(0);
+ if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
+ {
+ bool truncated = FALSE;
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ if (!dn->isVisible())
+ truncated = TRUE;
+ else
+ queue.append(dn);
+ }
+ }
+ n->markAsTruncated(truncated);
+ }
+ }
+}
+
+DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse)
+{
+ m_inverse = inverse;
+ m_diskName = md->getOutputFileBase()+"_"+md->anchor();
+ m_scope = md->getOuterScope();
+ QCString uniqueId;
+ uniqueId = md->getReference()+"$"+
+ md->getOutputFileBase()+"#"+md->anchor();
+ QCString name;
+ if (HIDE_SCOPE_NAMES)
+ {
+ name = md->name();
+ }
+ else
+ {
+ name = md->qualifiedName();
+ }
+ QCString tooltip = md->briefDescriptionAsTooltip();
+ m_startNode = new DotNode(getNextNodeNumber(),
+ linkToText(md->getLanguage(),name,FALSE),
+ tooltip,
+ uniqueId.data(),
+ TRUE // root node
+ );
+ m_startNode->setDistance(0);
+ m_usedNodes = new QDict<DotNode>(1009);
+ m_usedNodes->insert(uniqueId,m_startNode);
+ buildGraph(m_startNode,md,1);
+
+ int maxNodes = DOT_GRAPH_MAX_NODES;
+ QList<DotNode> openNodeQueue;
+ openNodeQueue.append(m_startNode);
+ determineVisibleNodes(openNodeQueue,maxNodes);
+ openNodeQueue.clear();
+ openNodeQueue.append(m_startNode);
+ determineTruncatedNodes(openNodeQueue);
+}
+
+DotCallGraph::~DotCallGraph()
+{
+ DotNode::deleteNodes(m_startNode);
+ delete m_usedNodes;
+}
+
+QCString DotCallGraph::getBaseName() const
+{
+ return m_diskName + (m_inverse ? "_icgraph" : "_cgraph");
+}
+
+void DotCallGraph::computeTheGraph()
+{
+ computeGraph(
+ m_startNode,
+ CallGraph,
+ m_graphFormat,
+ m_inverse ? "RL" : "LR",
+ FALSE,
+ m_inverse,
+ m_startNode->label(),
+ m_theGraph);
+}
+
+QCString DotCallGraph::getMapLabel() const
+{
+ return m_baseName;
+}
+
+QCString DotCallGraph::writeGraph(
+ FTextStream &out,
+ GraphOutputFormat graphFormat,
+ EmbeddedOutputFormat textFormat,
+ const char *path,
+ const char *fileName,
+ const char *relPath,bool generateImageMap,
+ int graphId)
+{
+ return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId);
+}
+
+bool DotCallGraph::isTrivial() const
+{
+ return m_startNode->children()==0;
+}
+
+bool DotCallGraph::isTooBig() const
+{
+ int numNodes = m_startNode->children() ? m_startNode->children()->count() : 0;
+ return numNodes>=DOT_GRAPH_MAX_NODES;
+}
diff --git a/src/dotcallgraph.h b/src/dotcallgraph.h
new file mode 100644
index 0000000..c96b9cf
--- /dev/null
+++ b/src/dotcallgraph.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTCALLGRAPH_H
+#define DOTCALLGRAPH_H
+
+#include "dotgraph.h"
+#include "ftextstream.h"
+#include "memberdef.h"
+
+/** Representation of an call graph */
+class DotCallGraph : public DotGraph
+{
+ public:
+ DotCallGraph(const MemberDef *md,bool inverse);
+ ~DotCallGraph();
+ bool isTrivial() const;
+ bool isTooBig() const;
+ QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
+ const char *path,const char *fileName,
+ const char *relPath,bool writeImageMap=TRUE,
+ int graphId=-1);
+
+ protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+
+ private:
+ void buildGraph(DotNode *n,const MemberDef *md,int distance);
+ void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes);
+ void determineTruncatedNodes(QList<DotNode> &queue);
+ DotNode *m_startNode;
+ QDict<DotNode> *m_usedNodes;
+ bool m_inverse;
+ QCString m_diskName;
+ const Definition * m_scope;
+};
+
+#endif
diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp
new file mode 100644
index 0000000..308be4b
--- /dev/null
+++ b/src/dotclassgraph.cpp
@@ -0,0 +1,548 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotclassgraph.h"
+#include "dotnode.h"
+
+#include "config.h"
+#include "util.h"
+
+#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES)
+#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH)
+#define UML_LOOK Config_getBool(UML_LOOK)
+#define TEMPLATE_RELATIONS Config_getBool(TEMPLATE_RELATIONS)
+#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES)
+
+void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot,
+ const char *label,const char *usedName,const char *templSpec,bool base,int distance)
+{
+ if (Config_getBool(HIDE_UNDOC_CLASSES) && !cd->isLinkable()) return;
+
+ int edgeStyle = (label || prot==EdgeInfo::Orange || prot==EdgeInfo::Orange2) ? EdgeInfo::Dashed : EdgeInfo::Solid;
+ QCString className;
+ if (cd->isAnonymous())
+ {
+ className="anonymous:";
+ className+=label;
+ }
+ else if (usedName) // name is a typedef
+ {
+ className=usedName;
+ }
+ else if (templSpec) // name has a template part
+ {
+ className=insertTemplateSpecifierInScope(cd->name(),templSpec);
+ }
+ else // just a normal name
+ {
+ className=cd->displayName();
+ }
+ //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n",
+ // className.data(),n->label().data(),prot,label,distance,usedName,templSpec,base);
+ DotNode *bn = m_usedNodes->find(className);
+ if (bn) // class already inserted
+ {
+ if (base)
+ {
+ n->addChild(bn,prot,edgeStyle,label);
+ bn->addParent(n);
+ }
+ else
+ {
+ bn->addChild(n,prot,edgeStyle,label);
+ n->addParent(bn);
+ }
+ bn->setDistance(distance);
+ //printf(" add exiting node %s of %s\n",bn->label().data(),n->label().data());
+ }
+ else // new class
+ {
+ QCString displayName=className;
+ if (HIDE_SCOPE_NAMES) displayName=stripScope(displayName);
+ QCString tmp_url;
+ if (cd->isLinkable() && !cd->isHidden())
+ {
+ tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
+ if (!cd->anchor().isEmpty())
+ {
+ tmp_url+="#"+cd->anchor();
+ }
+ }
+ QCString tooltip = cd->briefDescriptionAsTooltip();
+ bn = new DotNode(getNextNodeNumber(),
+ displayName,
+ tooltip,
+ tmp_url.data(),
+ FALSE, // rootNode
+ cd
+ );
+ if (base)
+ {
+ n->addChild(bn,prot,edgeStyle,label);
+ bn->addParent(n);
+ }
+ else
+ {
+ bn->addChild(n,prot,edgeStyle,label);
+ n->addParent(bn);
+ }
+ bn->setDistance(distance);
+ m_usedNodes->insert(className,bn);
+ //printf(" add new child node `%s' to %s hidden=%d url=%s\n",
+ // className.data(),n->label().data(),cd->isHidden(),tmp_url.data());
+
+ buildGraph(cd,bn,base,distance+1);
+ }
+}
+
+void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includeParents)
+{
+ while (queue.count()>0)
+ {
+ DotNode *n = queue.take(0);
+ if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
+ {
+ bool truncated = FALSE;
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ if (!dn->isVisible())
+ truncated = TRUE;
+ else
+ queue.append(dn);
+ }
+ }
+ if (n->parents() && includeParents)
+ {
+ QListIterator<DotNode> li(*n->parents());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ if (!dn->isVisible())
+ truncated = TRUE;
+ else
+ queue.append(dn);
+ }
+ }
+ n->markAsTruncated(truncated);
+ }
+ }
+}
+
+bool DotClassGraph::determineVisibleNodes(DotNode *rootNode,
+ int maxNodes,bool includeParents)
+{
+ QList<DotNode> childQueue;
+ QList<DotNode> parentQueue;
+ QArray<int> childTreeWidth;
+ QArray<int> parentTreeWidth;
+ childQueue.append(rootNode);
+ if (includeParents) parentQueue.append(rootNode);
+ bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop
+ // despite being marked visible in the child loop
+ while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0)
+ {
+ if (childQueue.count()>0)
+ {
+ DotNode *n = childQueue.take(0);
+ int distance = n->distance();
+ if (!n->isVisible() && distance<=MAX_DOT_GRAPH_DEPTH) // not yet processed
+ {
+ if (distance>0)
+ {
+ int oldSize=(int)childTreeWidth.size();
+ if (distance>oldSize)
+ {
+ childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance));
+ int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0;
+ }
+ childTreeWidth[distance-1]+=n->label().length();
+ }
+ n->markAsVisible();
+ maxNodes--;
+ // add direct children
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ childQueue.append(dn);
+ }
+ }
+ }
+ }
+ if (includeParents && parentQueue.count()>0)
+ {
+ DotNode *n = parentQueue.take(0);
+ if ((!n->isVisible() || firstNode) && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed
+ {
+ firstNode=FALSE;
+ int distance = n->distance();
+ if (distance>0)
+ {
+ int oldSize = (int)parentTreeWidth.size();
+ if (distance>oldSize)
+ {
+ parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance));
+ int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0;
+ }
+ parentTreeWidth[distance-1]+=n->label().length();
+ }
+ n->markAsVisible();
+ maxNodes--;
+ // add direct parents
+ if (n->parents())
+ {
+ QListIterator<DotNode> li(*n->parents());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ parentQueue.append(dn);
+ }
+ }
+ }
+ }
+ }
+ if (UML_LOOK) return FALSE; // UML graph are always top to bottom
+ int maxWidth=0;
+ int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size());
+ uint i;
+ for (i=0;i<childTreeWidth.size();i++)
+ {
+ if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i);
+ }
+ for (i=0;i<parentTreeWidth.size();i++)
+ {
+ if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i);
+ }
+ //printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight);
+ return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree
+ // from left to right instead of top to bottom,
+ // with the idea to render very wide trees in
+ // left to right order.
+}
+
+void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int distance)
+{
+ //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n",
+ // cd->name().data(),distance,base);
+ // ---- Add inheritance relations
+
+ if (m_graphType == Inheritance || m_graphType==Collaboration)
+ {
+ BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses();
+ if (bcl)
+ {
+ BaseClassListIterator bcli(*bcl);
+ BaseClassDef *bcd;
+ for ( ; (bcd=bcli.current()) ; ++bcli )
+ {
+ //printf("-------- inheritance relation %s->%s templ=`%s'\n",
+ // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data());
+ addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName,
+ bcd->templSpecifiers,base,distance);
+ }
+ }
+ }
+ if (m_graphType == Collaboration)
+ {
+ // ---- Add usage relations
+
+ UsesClassDict *dict =
+ base ? cd->usedImplementationClasses() :
+ cd->usedByImplementationClasses()
+ ;
+ if (dict)
+ {
+ UsesClassDictIterator ucdi(*dict);
+ UsesClassDef *ucd;
+ for (;(ucd=ucdi.current());++ucdi)
+ {
+ QCString label;
+ QDictIterator<void> dvi(*ucd->accessors);
+ const char *s;
+ bool first=TRUE;
+ int count=0;
+ int maxLabels=10;
+ for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
+ {
+ if (first)
+ {
+ label=s;
+ first=FALSE;
+ }
+ else
+ {
+ label+=QCString("\n")+s;
+ }
+ }
+ if (count==maxLabels) label+="\n...";
+ //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
+ addClass(ucd->classDef,n,EdgeInfo::Purple,label,0,
+ ucd->templSpecifiers,base,distance);
+ }
+ }
+ }
+ if (TEMPLATE_RELATIONS && base)
+ {
+ ConstraintClassDict *dict = cd->templateTypeConstraints();
+ if (dict)
+ {
+ ConstraintClassDictIterator ccdi(*dict);
+ ConstraintClassDef *ccd;
+ for (;(ccd=ccdi.current());++ccdi)
+ {
+ QCString label;
+ QDictIterator<void> dvi(*ccd->accessors);
+ const char *s;
+ bool first=TRUE;
+ int count=0;
+ int maxLabels=10;
+ for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count)
+ {
+ if (first)
+ {
+ label=s;
+ first=FALSE;
+ }
+ else
+ {
+ label+=QCString("\n")+s;
+ }
+ }
+ if (count==maxLabels) label+="\n...";
+ //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data());
+ addClass(ccd->classDef,n,EdgeInfo::Orange2,label,0,
+ 0,TRUE,distance);
+ }
+ }
+ }
+
+ // ---- Add template instantiation relations
+
+ if (TEMPLATE_RELATIONS)
+ {
+ if (base) // template relations for base classes
+ {
+ const ClassDef *templMaster=cd->templateMaster();
+ if (templMaster)
+ {
+ QDictIterator<ClassDef> cli(*templMaster->getTemplateInstances());
+ const ClassDef *templInstance;
+ for (;(templInstance=cli.current());++cli)
+ {
+ if (templInstance==cd)
+ {
+ addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0,
+ 0,TRUE,distance);
+ }
+ }
+ }
+ }
+ else // template relations for super classes
+ {
+ const QDict<ClassDef> *templInstances = cd->getTemplateInstances();
+ if (templInstances)
+ {
+ QDictIterator<ClassDef> cli(*templInstances);
+ const ClassDef *templInstance;
+ for (;(templInstance=cli.current());++cli)
+ {
+ addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0,
+ 0,FALSE,distance);
+ }
+ }
+ }
+ }
+}
+
+DotClassGraph::DotClassGraph(const ClassDef *cd,GraphType t)
+{
+ //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data());
+ m_graphType = t;
+ QCString tmp_url="";
+ if (cd->isLinkable() && !cd->isHidden())
+ {
+ tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
+ if (!cd->anchor().isEmpty())
+ {
+ tmp_url+="#"+cd->anchor();
+ }
+ }
+ QCString className = cd->displayName();
+ QCString tooltip = cd->briefDescriptionAsTooltip();
+ m_startNode = new DotNode(getNextNodeNumber(),
+ className,
+ tooltip,
+ tmp_url.data(),
+ TRUE, // is a root node
+ cd
+ );
+ m_startNode->setDistance(0);
+ m_usedNodes = new QDict<DotNode>(1009);
+ m_usedNodes->insert(className,m_startNode);
+
+ buildGraph(cd,m_startNode,TRUE,1);
+ if (t==Inheritance) buildGraph(cd,m_startNode,FALSE,1);
+
+ m_lrRank = determineVisibleNodes(m_startNode,DOT_GRAPH_MAX_NODES,t==Inheritance);
+ QList<DotNode> openNodeQueue;
+ openNodeQueue.append(m_startNode);
+ determineTruncatedNodes(openNodeQueue,t==Inheritance);
+
+ m_collabFileName = cd->collaborationGraphFileName();
+ m_inheritFileName = cd->inheritanceGraphFileName();
+}
+
+bool DotClassGraph::isTrivial() const
+{
+ if (m_graphType==Inheritance)
+ return m_startNode->children()==0 && m_startNode->parents()==0;
+ else
+ return !UML_LOOK && m_startNode->children()==0;
+}
+
+bool DotClassGraph::isTooBig() const
+{
+ int numNodes = 0;
+ numNodes+= m_startNode->children() ? m_startNode->children()->count() : 0;
+ if (m_graphType==Inheritance)
+ {
+ numNodes+= m_startNode->parents() ? m_startNode->parents()->count() : 0;
+ }
+ return numNodes>=DOT_GRAPH_MAX_NODES;
+}
+
+DotClassGraph::~DotClassGraph()
+{
+ DotNode::deleteNodes(m_startNode);
+ delete m_usedNodes;
+}
+
+QCString DotClassGraph::getBaseName() const
+{
+ switch (m_graphType)
+ {
+ case Collaboration:
+ return m_collabFileName;
+ break;
+ case Inheritance:
+ return m_inheritFileName;
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ return "";
+}
+
+void DotClassGraph::computeTheGraph()
+{
+ computeGraph(
+ m_startNode,
+ m_graphType,
+ m_graphFormat,
+ m_lrRank ? "LR" : "",
+ m_graphType == Inheritance,
+ TRUE,
+ m_startNode->label(),
+ m_theGraph
+ );
+}
+
+QCString DotClassGraph::getMapLabel() const
+{
+ QCString mapName;
+ switch (m_graphType)
+ {
+ case Collaboration:
+ mapName="coll_map";
+ break;
+ case Inheritance:
+ mapName="inherit_map";
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ return escapeCharsInString(m_startNode->label(),FALSE)+"_"+escapeCharsInString(mapName,FALSE);
+}
+
+QCString DotClassGraph::getImgAltText() const
+{
+ switch (m_graphType)
+ {
+ case Collaboration:
+ return "Collaboration graph";
+ break;
+ case Inheritance:
+ return "Inheritance graph";
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ return "";
+}
+
+QCString DotClassGraph::writeGraph(FTextStream &out,
+ GraphOutputFormat graphFormat,
+ EmbeddedOutputFormat textFormat,
+ const char *path,
+ const char *fileName,
+ const char *relPath,
+ bool /*isTBRank*/,
+ bool generateImageMap,
+ int graphId)
+{
+ return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId);
+}
+
+//--------------------------------------------------------------------
+
+void DotClassGraph::writeXML(FTextStream &t)
+{
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *node;
+ for (;(node=dni.current());++dni)
+ {
+ node->writeXML(t,TRUE);
+ }
+}
+
+void DotClassGraph::writeDocbook(FTextStream &t)
+{
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *node;
+ for (;(node=dni.current());++dni)
+ {
+ node->writeDocbook(t,TRUE);
+ }
+}
+
+void DotClassGraph::writeDEF(FTextStream &t)
+{
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *node;
+ for (;(node=dni.current());++dni)
+ {
+ node->writeDEF(t);
+ }
+}
diff --git a/src/dotclassgraph.h b/src/dotclassgraph.h
new file mode 100644
index 0000000..b3b9291
--- /dev/null
+++ b/src/dotclassgraph.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTCLASSGRAPH_H
+#define DOTCLASSGRAPH_H
+
+#include "classdef.h"
+
+#include "dotgraph.h"
+
+/** Representation of a class inheritance or dependency graph */
+class DotClassGraph : public DotGraph
+{
+public:
+ DotClassGraph(const ClassDef *cd,GraphType t);
+ ~DotClassGraph();
+ bool isTrivial() const;
+ bool isTooBig() const;
+ QCString writeGraph(FTextStream &t,GraphOutputFormat gf,EmbeddedOutputFormat ef,
+ const char *path, const char *fileName, const char *relPath,
+ bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1);
+
+ void writeXML(FTextStream &t);
+ void writeDocbook(FTextStream &t);
+ void writeDEF(FTextStream &t);
+
+protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+ virtual QCString getImgAltText() const;
+
+private:
+ void buildGraph(const ClassDef *cd,DotNode *n,bool base,int distance);
+ bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents);
+ void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents);
+ void addClass(const ClassDef *cd,DotNode *n,int prot,const char *label,
+ const char *usedName,const char *templSpec,
+ bool base,int distance);
+
+ DotNode * m_startNode;
+ QDict<DotNode> * m_usedNodes;
+ GraphType m_graphType;
+ QCString m_collabFileName;
+ QCString m_inheritFileName;
+ bool m_lrRank;
+};
+
+
+#endif
diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp
new file mode 100644
index 0000000..85906d1
--- /dev/null
+++ b/src/dotdirdeps.cpp
@@ -0,0 +1,220 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotdirdeps.h"
+
+#include "ftextstream.h"
+#include "util.h"
+#include "doxygen.h"
+#include "config.h"
+
+void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations)
+{
+ t << "digraph \"" << dd->displayName() << "\" {\n";
+ if (Config_getBool(DOT_TRANSPARENT))
+ {
+ t << " bgcolor=transparent;\n";
+ }
+ t << " compound=true\n";
+ t << " node [ fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", fontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n";
+ t << " edge [ labelfontsize=\"" << DotGraph::DOT_FONTSIZE << "\", labelfontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n";
+
+ QDict<DirDef> dirsInGraph(257);
+
+ dirsInGraph.insert(dd->getOutputFileBase(),dd);
+ if (dd->parent())
+ {
+ t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n";
+ t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\""
+ << dd->parent()->shortName()
+ << "\" fontname=\"" << DotGraph::DOT_FONTNAME << "\", fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", URL=\"";
+ t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension;
+ t << "\"]\n";
+ }
+ if (dd->isCluster())
+ {
+ t << " subgraph cluster" << dd->getOutputFileBase() << " {\n";
+ t << " graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\""
+ << " URL=\"" << dd->getOutputFileBase() << Doxygen::htmlFileExtension
+ << "\"];\n";
+ t << " " << dd->getOutputFileBase() << " [shape=plaintext label=\""
+ << dd->shortName() << "\"];\n";
+
+ // add nodes for sub directories
+ QListIterator<DirDef> sdi(dd->subDirs());
+ const DirDef *sdir;
+ for (sdi.toFirst();(sdir=sdi.current());++sdi)
+ {
+ t << " " << sdir->getOutputFileBase() << " [shape=box label=\""
+ << sdir->shortName() << "\"";
+ if (sdir->isCluster())
+ {
+ t << " color=\"red\"";
+ }
+ else
+ {
+ t << " color=\"black\"";
+ }
+ t << " fillcolor=\"white\" style=\"filled\"";
+ t << " URL=\"" << sdir->getOutputFileBase()
+ << Doxygen::htmlFileExtension << "\"";
+ t << "];\n";
+ dirsInGraph.insert(sdir->getOutputFileBase(),sdir);
+ }
+ t << " }\n";
+ }
+ else
+ {
+ t << " " << dd->getOutputFileBase() << " [shape=box, label=\""
+ << dd->shortName() << "\", style=\"filled\", fillcolor=\"#eeeeff\","
+ << " pencolor=\"black\", URL=\"" << dd->getOutputFileBase()
+ << Doxygen::htmlFileExtension << "\"];\n";
+ }
+ if (dd->parent())
+ {
+ t << " }\n";
+ }
+
+ // add nodes for other used directories
+ QDictIterator<UsedDir> udi(*dd->usedDirs());
+ UsedDir *udir;
+ //printf("*** For dir %s\n",shortName().data());
+ for (udi.toFirst();(udir=udi.current());++udi)
+ // for each used dir (=directly used or a parent of a directly used dir)
+ {
+ const DirDef *usedDir=udir->dir();
+ const DirDef *dir=dd;
+ while (dir)
+ {
+ //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n",
+ // dir->shortName().data(),usedDir->shortName().data(),
+ // dir->parent()==usedDir->parent(),
+ // usedDir->shortName().data(),
+ // shortName().data(),
+ // !usedDir->isParentOf(this)
+ // );
+ if (dir!=usedDir && dir->parent()==usedDir->parent() &&
+ !usedDir->isParentOf(dd))
+ // include if both have the same parent (or no parent)
+ {
+ t << " " << usedDir->getOutputFileBase() << " [shape=box label=\""
+ << usedDir->shortName() << "\"";
+ if (usedDir->isCluster())
+ {
+ if (!Config_getBool(DOT_TRANSPARENT))
+ {
+ t << " fillcolor=\"white\" style=\"filled\"";
+ }
+ t << " color=\"red\"";
+ }
+ t << " URL=\"" << usedDir->getOutputFileBase()
+ << Doxygen::htmlFileExtension << "\"];\n";
+ dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir);
+ break;
+ }
+ dir=dir->parent();
+ }
+ }
+
+ // add relations between all selected directories
+ const DirDef *dir;
+ QDictIterator<DirDef> di(dirsInGraph);
+ for (di.toFirst();(dir=di.current());++di) // foreach dir in the graph
+ {
+ QDictIterator<UsedDir> udi(*dir->usedDirs());
+ UsedDir *udir;
+ for (udi.toFirst();(udir=udi.current());++udi) // foreach used dir
+ {
+ const DirDef *usedDir=udir->dir();
+ if ((dir!=dd || !udir->inherited()) && // only show direct dependendies for this dir
+ (usedDir!=dd || !udir->inherited()) && // only show direct dependendies for this dir
+ !usedDir->isParentOf(dir) && // don't point to own parent
+ dirsInGraph.find(usedDir->getOutputFileBase())) // only point to nodes that are in the graph
+ {
+ QCString relationName;
+ relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount());
+ if (Doxygen::dirRelations.find(relationName)==0)
+ {
+ // new relation
+ Doxygen::dirRelations.append(relationName,
+ new DirRelation(relationName,dir,udir));
+ }
+ int nrefs = udir->filePairs().count();
+ t << " " << dir->getOutputFileBase() << "->"
+ << usedDir->getOutputFileBase();
+ t << " [headlabel=\"" << nrefs << "\", labeldistance=1.5";
+ if (linkRelations)
+ {
+ t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\"";
+ }
+ t << "];\n";
+ }
+ }
+ }
+
+ t << "}\n";
+}
+
+DotDirDeps::DotDirDeps(const DirDef *dir) : m_dir(dir)
+{
+}
+
+DotDirDeps::~DotDirDeps()
+{
+}
+
+QCString DotDirDeps::getBaseName() const
+{
+ return m_dir->getOutputFileBase()+"_dep";
+
+}
+
+void DotDirDeps::computeTheGraph()
+{
+ // compute md5 checksum of the graph were are about to generate
+ FTextStream md5stream(&m_theGraph);
+ //m_dir->writeDepGraph(md5stream);
+ writeDotDirDepGraph(md5stream,m_dir,m_linkRelations);
+}
+
+QCString DotDirDeps::getMapLabel() const
+{
+ return escapeCharsInString(m_baseName,FALSE);
+}
+
+QCString DotDirDeps::getImgAltText() const
+{
+ return convertToXML(m_dir->displayName());
+}
+
+QCString DotDirDeps::writeGraph(FTextStream &out,
+ GraphOutputFormat graphFormat,
+ EmbeddedOutputFormat textFormat,
+ const char *path,
+ const char *fileName,
+ const char *relPath,
+ bool generateImageMap,
+ int graphId,
+ bool linkRelations)
+{
+ m_linkRelations = linkRelations;
+ m_urlOnly = TRUE;
+ return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId);
+}
+
+bool DotDirDeps::isTrivial() const
+{
+ return m_dir->depGraphIsTrivial();
+}
diff --git a/src/dotdirdeps.h b/src/dotdirdeps.h
new file mode 100644
index 0000000..f5eef65
--- /dev/null
+++ b/src/dotdirdeps.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTDIRDEPS_H
+#define DOTDIRDEPS_H
+
+#include "dotgraph.h"
+#include "dirdef.h"
+
+/** Representation of an directory dependency graph */
+class DotDirDeps : public DotGraph
+{
+ public:
+ DotDirDeps(const DirDef *dir);
+ ~DotDirDeps();
+ bool isTrivial() const;
+ QCString writeGraph(FTextStream &out,
+ GraphOutputFormat gf,
+ EmbeddedOutputFormat ef,
+ const char *path,
+ const char *fileName,
+ const char *relPath,
+ bool writeImageMap=TRUE,
+ int graphId=-1,
+ bool linkRelations=TRUE);
+
+ protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+ virtual QCString getImgAltText() const;
+
+ private:
+ const DirDef *m_dir;
+
+ bool m_linkRelations;
+};
+
+#endif
diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp
new file mode 100644
index 0000000..91b7c78
--- /dev/null
+++ b/src/dotfilepatcher.cpp
@@ -0,0 +1,539 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotfilepatcher.h"
+
+#include "qstring.h"
+#include "config.h"
+#include "qdir.h"
+#include "message.h"
+#include "ftextstream.h"
+#include "docparser.h"
+#include "doxygen.h"
+#include "util.h"
+#include "dot.h"
+
+static const char svgZoomHeader[] =
+"<svg id=\"main\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" onload=\"init(evt)\">\n"
+"<style type=\"text/css\"><![CDATA[\n"
+".edge:hover path { stroke: red; }\n"
+".edge:hover polygon { stroke: red; fill: red; }\n"
+"]]></style>\n"
+"<script type=\"text/javascript\"><![CDATA[\n"
+"var edges = document.getElementsByTagName('g');\n"
+"if (edges && edges.length) {\n"
+" for (var i=0;i<edges.length;i++) {\n"
+" if (edges[i].id.substr(0,4)=='edge') {\n"
+" edges[i].setAttribute('class','edge');\n"
+" }\n"
+" }\n"
+"}\n"
+"]]></script>\n"
+" <defs>\n"
+" <circle id=\"rim\" cx=\"0\" cy=\"0\" r=\"7\"/>\n"
+" <circle id=\"rim2\" cx=\"0\" cy=\"0\" r=\"3.5\"/>\n"
+" <g id=\"zoomPlus\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomplus.mouseover\" end=\"zoomplus.mouseout\"/>\n"
+" </use>\n"
+" <path d=\"M-4,0h8M0,-4v8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
+" </g>\n"
+" <g id=\"zoomMin\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomminus.mouseover\" end=\"zoomminus.mouseout\"/>\n"
+" </use>\n"
+" <path d=\"M-4,0h8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n"
+" </g>\n"
+" <g id=\"dirArrow\">\n"
+" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
+" </g>\n"
+" <g id=\"resetDef\">\n"
+" <use xlink:href=\"#rim2\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"reset.mouseover\" end=\"reset.mouseout\"/>\n"
+" </use>\n"
+" </g>\n"
+" </defs>\n"
+"\n"
+"<script type=\"text/javascript\">\n"
+;
+
+static const char svgZoomFooter[] =
+// navigation panel
+" <g id=\"navigator\" transform=\"translate(0 0)\" fill=\"#404254\">\n"
+" <rect fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\".5\" x=\"0\" y=\"0\" width=\"60\" height=\"60\"/>\n"
+// zoom in
+" <use id=\"zoomplus\" xlink:href=\"#zoomPlus\" x=\"17\" y=\"9\" onmousedown=\"handleZoom(evt,'in')\"/>\n"
+// zoom out
+" <use id=\"zoomminus\" xlink:href=\"#zoomMin\" x=\"42\" y=\"9\" onmousedown=\"handleZoom(evt,'out')\"/>\n"
+// reset zoom
+" <use id=\"reset\" xlink:href=\"#resetDef\" x=\"30\" y=\"36\" onmousedown=\"handleReset()\"/>\n"
+// arrow up
+" <g id=\"arrowUp\" xlink:href=\"#dirArrow\" transform=\"translate(30 24)\" onmousedown=\"handlePan(0,-1)\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowUp.mouseover\" end=\"arrowUp.mouseout\"/>\n"
+" </use>\n"
+" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
+" </g>\n"
+// arrow right
+" <g id=\"arrowRight\" xlink:href=\"#dirArrow\" transform=\"rotate(90) translate(36 -43)\" onmousedown=\"handlePan(1,0)\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowRight.mouseover\" end=\"arrowRight.mouseout\"/>\n"
+" </use>\n"
+" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
+" </g>\n"
+// arrow down
+" <g id=\"arrowDown\" xlink:href=\"#dirArrow\" transform=\"rotate(180) translate(-30 -48)\" onmousedown=\"handlePan(0,1)\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowDown.mouseover\" end=\"arrowDown.mouseout\"/>\n"
+" </use>\n"
+" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
+" </g>\n"
+// arrow left
+" <g id=\"arrowLeft\" xlink:href=\"#dirArrow\" transform=\"rotate(270) translate(-36 17)\" onmousedown=\"handlePan(-1,0)\">\n"
+" <use xlink:href=\"#rim\" fill=\"#404040\">\n"
+" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowLeft.mouseover\" end=\"arrowLeft.mouseout\"/>\n"
+" </use>\n"
+" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n"
+" </g>\n"
+" </g>\n"
+// link to original SVG
+" <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n"
+" <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n"
+" <a xlink:href=\"$orgname\" target=\"_base\">\n"
+" <rect id=\"button\" ry=\"5\" rx=\"5\" y=\"6\" x=\"6\" height=\"38\" width=\"38\"\n"
+" fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\"1.0\"/>\n"
+" <path id=\"arrow\"\n"
+" d=\"M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z\"\n"
+" style=\"fill:#404040;\"/>\n"
+" </a>\n"
+" </g>\n"
+" </svg>\n"
+"</svg>\n"
+;
+
+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;
+ bool setTarget = FALSE;
+ 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();
+ if (result != "") setTarget = TRUE;
+ }
+ result+= href+"=\"";
+ result+=externalRef(relPath,ref,TRUE);
+ result+= url + "\"";
+ }
+ else // should not happen, but handle properly anyway
+ {
+ result = href+"=\"" + link + "\"";
+ }
+ }
+ if (!target.isEmpty() && !setTarget)
+ {
+ 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.
+* \param relPath the relative path to the root of the output directory
+* (used in case CREATE_SUBDIRS is enabled).
+* \param urlOnly if FALSE the url field in the map contains an external
+* references followed by a $ and then the URL.
+* \param context the context (file, class, or namespace) in which the
+* map file was found
+* \returns TRUE if successful.
+*/
+bool convertMapFile(FTextStream &t,const char *mapName,
+ const QCString relPath, bool urlOnly,
+ const QCString &context)
+{
+ QFile f(mapName);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("problems opening map file %s for inclusion in the docs!\n"
+ "If you installed Graphviz/dot after a previous failing run, \n"
+ "try deleting the output directory and rerun doxygen.\n",mapName);
+ return FALSE;
+ }
+ const int maxLineLen=10240;
+ while (!f.atEnd()) // foreach line
+ {
+ QCString buf(maxLineLen);
+ int numBytes = f.readLine(buf.rawData(),maxLineLen);
+ if (numBytes>0)
+ {
+ buf.resize(numBytes+1);
+
+ if (buf.left(5)=="<area")
+ {
+ QCString replBuf = replaceRef(buf,relPath,urlOnly,context);
+ // strip id="..." from replBuf since the id's are not needed and not unique.
+ int indexS = replBuf.find("id=\""), indexE;
+ if (indexS>0 && (indexE=replBuf.find('"',indexS+4))!=-1)
+ {
+ t << replBuf.left(indexS-1) << replBuf.right(replBuf.length() - indexE - 1);
+ }
+ else
+ {
+ t << replBuf;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+DotFilePatcher::DotFilePatcher(const char *patchFile)
+ : m_patchFile(patchFile)
+{
+ m_maps.setAutoDelete(TRUE);
+}
+
+QCString DotFilePatcher::file() const
+{
+ return m_patchFile;
+}
+
+int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath,
+ bool urlOnly,const QCString &context,const QCString &label)
+{
+ int id = m_maps.count();
+ Map *map = new Map;
+ map->mapFile = mapFile;
+ map->relPath = relPath;
+ map->urlOnly = urlOnly;
+ map->context = context;
+ map->label = label;
+ map->zoomable = FALSE;
+ map->graphId = -1;
+ m_maps.append(map);
+ return id;
+}
+
+int DotFilePatcher::addFigure(const QCString &baseName,
+ const QCString &figureName,bool heightCheck)
+{
+ int id = m_maps.count();
+ Map *map = new Map;
+ map->mapFile = figureName;
+ map->urlOnly = heightCheck;
+ map->label = baseName;
+ map->zoomable = FALSE;
+ map->graphId = -1;
+ m_maps.append(map);
+ return id;
+}
+
+int DotFilePatcher::addSVGConversion(const QCString &relPath,bool urlOnly,
+ const QCString &context,bool zoomable,
+ int graphId)
+{
+ int id = m_maps.count();
+ Map *map = new Map;
+ map->relPath = relPath;
+ map->urlOnly = urlOnly;
+ map->context = context;
+ map->zoomable = zoomable;
+ map->graphId = graphId;
+ 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;
+ map->zoomable = FALSE;
+ map->graphId = -1;
+ m_maps.append(map);
+ return id;
+}
+
+bool DotFilePatcher::run()
+{
+ //printf("DotFilePatcher::run(): %s\n",m_patchFile.data());
+ bool interactiveSVG_local = Config_getBool(INTERACTIVE_SVG);
+ bool isSVGFile = m_patchFile.right(4)==".svg";
+ int graphId = -1;
+ QCString relPath;
+ if (isSVGFile)
+ {
+ Map *map = m_maps.at(0); // there is only one 'map' for a SVG file
+ interactiveSVG_local = interactiveSVG_local && map->zoomable;
+ graphId = map->graphId;
+ relPath = map->relPath;
+ //printf("DotFilePatcher::addSVGConversion: file=%s zoomable=%d\n",
+ // m_patchFile.data(),map->zoomable);
+ }
+ QString tmpName = QString::fromUtf8(m_patchFile+".tmp");
+ QString patchFile = QString::fromUtf8(m_patchFile);
+ if (!QDir::current().rename(patchFile,tmpName))
+ {
+ err("Failed to rename file %s to %s!\n",m_patchFile.data(),tmpName.data());
+ return FALSE;
+ }
+ QFile fi(tmpName);
+ QFile fo(patchFile);
+ if (!fi.open(IO_ReadOnly))
+ {
+ err("problem opening file %s for patching!\n",tmpName.data());
+ QDir::current().rename(tmpName,patchFile);
+ return FALSE;
+ }
+ if (!fo.open(IO_WriteOnly))
+ {
+ err("problem opening file %s for patching!\n",m_patchFile.data());
+ QDir::current().rename(tmpName,patchFile);
+ return FALSE;
+ }
+ FTextStream t(&fo);
+ const int maxLineLen=100*1024;
+ int lineNr=1;
+ int width,height;
+ bool insideHeader=FALSE;
+ bool replacedHeader=FALSE;
+ bool foundSize=FALSE;
+ while (!fi.atEnd()) // foreach line
+ {
+ QCString line(maxLineLen);
+ int numBytes = fi.readLine(line.rawData(),maxLineLen);
+ if (numBytes<=0)
+ {
+ break;
+ }
+ line.resize(numBytes+1);
+
+ //printf("line=[%s]\n",line.stripWhiteSpace().data());
+ int i;
+ ASSERT(numBytes<maxLineLen);
+ if (isSVGFile)
+ {
+ if (interactiveSVG_local)
+ {
+ if (line.find("<svg")!=-1 && !replacedHeader)
+ {
+ int count;
+ count = sscanf(line.data(),"<svg width=\"%dpt\" height=\"%dpt\"",&width,&height);
+ //printf("width=%d height=%d\n",width,height);
+ foundSize = count==2 && (width>500 || height>450);
+ if (foundSize) insideHeader=TRUE;
+ }
+ else if (insideHeader && !replacedHeader && line.find("<title>")!=-1)
+ {
+ if (foundSize)
+ {
+ // insert special replacement header for interactive SVGs
+ t << "<!--zoomable " << height << " -->\n";
+ t << svgZoomHeader;
+ t << "var viewWidth = " << width << ";\n";
+ t << "var viewHeight = " << height << ";\n";
+ if (graphId>=0)
+ {
+ t << "var sectionId = 'dynsection-" << graphId << "';\n";
+ }
+ t << "</script>\n";
+ t << "<script xlink:href=\"" << relPath << "svgpan.js\"/>\n";
+ t << "<svg id=\"graph\" class=\"graph\">\n";
+ t << "<g id=\"viewport\">\n";
+ }
+ insideHeader=FALSE;
+ replacedHeader=TRUE;
+ }
+ }
+ if (!insideHeader || !foundSize) // copy SVG and replace refs,
+ // unless we are inside the header of the SVG.
+ // Then we replace it with another header.
+ {
+ 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);
+ //printf("DotFilePatcher::writeSVGFigure: file=%s zoomable=%d\n",
+ // m_patchFile.data(),map->zoomable);
+ 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;
+ t << line.left(i);
+ int n = sscanf(line.data()+i,"<!-- MAP %d",&mapId);
+ if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
+ {
+ QGString result;
+ FTextStream tt(&result);
+ Map *map = m_maps.at(mapId);
+ //printf("patching MAP %d in file %s with contents of %s\n",
+ // mapId,m_patchFile.data(),map->mapFile.data());
+ convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context);
+ if (!result.isEmpty())
+ {
+ t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl;
+ t << result;
+ t << "</map>" << endl;
+ }
+ }
+ else // error invalid map id!
+ {
+ err("Found invalid MAP id in file %s!\n",m_patchFile.data());
+ t << line.mid(i);
+ }
+ }
+ else if ((i=line.find("% FIG"))!=-1)
+ {
+ int mapId=-1;
+ int n = sscanf(line.data()+i+2,"FIG %d",&mapId);
+ //printf("line='%s' n=%d\n",line.data()+i,n);
+ if (n==1 && mapId>=0 && mapId<(int)m_maps.count())
+ {
+ Map *map = m_maps.at(mapId);
+ //printf("patching FIG %d in file %s with contents of %s\n",
+ // mapId,m_patchFile.data(),map->mapFile.data());
+ if (!DotGraph::writeVecGfxFigure(t,map->label,map->mapFile))
+ {
+ err("problem writing FIG %d figure!\n",mapId);
+ return FALSE;
+ }
+ }
+ else // error invalid map id!
+ {
+ err("Found invalid bounding FIG %d in file %s!\n",mapId,m_patchFile.data());
+ t << line;
+ }
+ }
+ else
+ {
+ t << line;
+ }
+ lineNr++;
+ }
+ fi.close();
+ if (isSVGFile && interactiveSVG_local && replacedHeader)
+ {
+ QCString orgName=m_patchFile.left(m_patchFile.length()-4)+"_org.svg";
+ t << substitute(svgZoomFooter,"$orgname",stripPath(orgName));
+ fo.close();
+ // keep original SVG file so we can refer to it, we do need to replace
+ // dummy link by real ones
+ QFile fi(tmpName);
+ QFile fo(orgName);
+ if (!fi.open(IO_ReadOnly))
+ {
+ err("problem opening file %s for reading!\n",tmpName.data());
+ return FALSE;
+ }
+ if (!fo.open(IO_WriteOnly))
+ {
+ err("problem opening file %s for writing!\n",orgName.data());
+ return FALSE;
+ }
+ FTextStream t(&fo);
+ while (!fi.atEnd()) // foreach line
+ {
+ QCString line(maxLineLen);
+ int numBytes = fi.readLine(line.rawData(),maxLineLen);
+ if (numBytes<=0)
+ {
+ break;
+ }
+ line.resize(numBytes+1);
+ 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");
+ }
+ fi.close();
+ fo.close();
+ }
+ // remove temporary file
+ QDir::current().remove(tmpName);
+ return TRUE;
+}
diff --git a/src/dotfilepatcher.h b/src/dotfilepatcher.h
new file mode 100644
index 0000000..dd5c511
--- /dev/null
+++ b/src/dotfilepatcher.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTFILEPATCHER_H
+#define DOTFILEPATCHER_H
+
+#include "qcstring.h"
+#include "qlist.h"
+
+/** Helper class to insert a set of map file into an output file */
+class DotFilePatcher
+{
+ public:
+ 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,bool zoomable,int graphId);
+ int addSVGObject(const QCString &baseName, const QCString &figureName,
+ const QCString &relPath);
+ bool run();
+ QCString file() const;
+
+ private:
+ struct Map
+ {
+ QCString mapFile;
+ QCString relPath;
+ bool urlOnly;
+ QCString context;
+ QCString label;
+ bool zoomable;
+ int graphId;
+ };
+ QList<Map> m_maps;
+ QCString m_patchFile;
+};
+
+#endif
diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp
new file mode 100644
index 0000000..0082b7e
--- /dev/null
+++ b/src/dotgfxhierarchytable.cpp
@@ -0,0 +1,302 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotgfxhierarchytable.h"
+
+#include "language.h"
+#include "util.h"
+#include "message.h"
+#include "doxygen.h"
+#include "classlist.h"
+
+#define OPTIMIZE_OUTPUT_SLICE Config_getBool(OPTIMIZE_OUTPUT_SLICE)
+
+QCString DotGfxHierarchyTable::getBaseName() const
+{
+ QCString baseName;
+ if (m_prefix.isEmpty())
+ baseName.sprintf("inherit_graph_%d", m_graphId);
+ else
+ baseName.sprintf("%sinherit_graph_%d",m_prefix.data(), m_graphId);
+ return baseName;
+}
+
+void DotGfxHierarchyTable::computeTheGraph()
+{
+ QListIterator<DotNode> dnli2(*m_rootNodes);
+ DotNode *node;
+
+ FTextStream md5stream(&m_theGraph);
+ writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy());
+ md5stream << " rankdir=\"LR\";" << endl;
+ for (dnli2.toFirst();(node=dnli2.current());++dnli2)
+ {
+ if (node->subgraphId()==m_rootSubgraphNode->subgraphId())
+ {
+ node->clearWriteFlag();
+ }
+ }
+ for (dnli2.toFirst();(node=dnli2.current());++dnli2)
+ {
+ if (node->subgraphId()==m_rootSubgraphNode->subgraphId())
+ {
+ node->write(md5stream,Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE);
+ }
+ }
+ writeGraphFooter(md5stream);
+
+}
+
+QCString DotGfxHierarchyTable::getMapLabel() const
+{
+ return escapeCharsInString(m_rootSubgraphNode->label(),FALSE);
+}
+
+void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out,
+ const char *path,const char *fileName,int id)
+{
+ m_rootSubgraphNode = n;
+ m_graphId = id;
+ m_noDivTag = TRUE;
+ m_zoomable = FALSE;
+ DotGraph::writeGraph(out, GOF_BITMAP, EOF_Html, path, fileName, "", TRUE, 0);
+}
+
+void DotGfxHierarchyTable::writeGraph(FTextStream &out,
+ const char *path,const char *fileName)
+{
+ //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name);
+ //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count());
+
+ if (m_rootSubgraphs->count()==0) return;
+
+ QDir d(path);
+ // store the original directory
+ if (!d.exists())
+ {
+ err("Output dir %s does not exist!\n",path); exit(1);
+ }
+
+ // put each connected subgraph of the hierarchy in a row of the HTML output
+ out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl;
+
+ QListIterator<DotNode> dnli(*m_rootSubgraphs);
+ DotNode *n;
+ int count=0;
+ for (dnli.toFirst();(n=dnli.current());++dnli)
+ {
+ out << "<tr><td>";
+ createGraph(n,out,path,fileName,count++);
+ out << "</td></tr>" << endl;
+ }
+ out << "</table>" << endl;
+}
+
+void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,bool hideSuper)
+{
+ //printf("addHierarchy `%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count());
+ if (cd->subClasses())
+ {
+ BaseClassListIterator bcli(*cd->subClasses());
+ BaseClassDef *bcd;
+ for ( ; (bcd=bcli.current()) ; ++bcli )
+ {
+ ClassDef *bClass=bcd->classDef;
+ //printf(" Trying sub class=`%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count());
+ if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses()))
+ {
+ DotNode *bn;
+ //printf(" Node `%s' Found visible class=`%s'\n",n->label().data(),
+ // bClass->name().data());
+ if ((bn=m_usedNodes->find(bClass->name()))) // node already present
+ {
+ if (n->children()==0 || n->children()->findRef(bn)==-1) // no arrow yet
+ {
+ n->addChild(bn,bcd->prot);
+ bn->addParent(n);
+ //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n",
+ // n->label().data(),
+ // bn->label().data(),
+ // bn->children() ? bn->children()->count() : 0,
+ // bn->parents() ? bn->parents()->count() : 0
+ // );
+ }
+ //else
+ //{
+ // printf(" Class already has an arrow!\n");
+ //}
+ }
+ else
+ {
+ QCString tmp_url="";
+ if (bClass->isLinkable() && !bClass->isHidden())
+ {
+ tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase();
+ if (!bClass->anchor().isEmpty())
+ {
+ tmp_url+="#"+bClass->anchor();
+ }
+ }
+ QCString tooltip = bClass->briefDescriptionAsTooltip();
+ bn = new DotNode(getNextNodeNumber(),
+ bClass->displayName(),
+ tooltip,
+ tmp_url.data()
+ );
+ n->addChild(bn,bcd->prot);
+ bn->addParent(n);
+ //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n",
+ // n->label().data(),
+ // bn->label().data(),
+ // bn->children() ? bn->children()->count() : 0,
+ // bn->parents() ? bn->parents()->count() : 0
+ // );
+ //printf(" inserting %s (%p)\n",bClass->name().data(),bn);
+ m_usedNodes->insert(bClass->name(),bn); // add node to the used list
+ }
+ if (!bClass->isVisited() && !hideSuper && bClass->subClasses())
+ {
+ bool wasVisited=bClass->isVisited();
+ bClass->setVisited(TRUE);
+ addHierarchy(bn,bClass,wasVisited);
+ }
+ }
+ }
+ }
+ //printf("end addHierarchy\n");
+}
+
+void DotGfxHierarchyTable::addClassList(const ClassSDict *cl)
+{
+ ClassSDict::Iterator cli(*cl);
+ ClassDef *cd;
+ for (cli.toLast();(cd=cli.current());--cli)
+ {
+ //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count());
+ if (cd->getLanguage()==SrcLangExt_VHDL &&
+ (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS
+ )
+ {
+ continue;
+ }
+ if (OPTIMIZE_OUTPUT_SLICE && cd->compoundType() != m_classType)
+ {
+ continue;
+ }
+ if (!hasVisibleRoot(cd->baseClasses()) &&
+ cd->isVisibleInHierarchy()
+ ) // root node in the forest
+ {
+ QCString tmp_url="";
+ if (cd->isLinkable() && !cd->isHidden())
+ {
+ tmp_url=cd->getReference()+"$"+cd->getOutputFileBase();
+ if (!cd->anchor().isEmpty())
+ {
+ tmp_url+="#"+cd->anchor();
+ }
+ }
+ //printf("Inserting root class %s\n",cd->name().data());
+ QCString tooltip = cd->briefDescriptionAsTooltip();
+ DotNode *n = new DotNode(getNextNodeNumber(),
+ cd->displayName(),
+ tooltip,
+ tmp_url.data());
+
+ //m_usedNodes->clear();
+ m_usedNodes->insert(cd->name(),n);
+ m_rootNodes->insert(0,n);
+ if (!cd->isVisited() && cd->subClasses())
+ {
+ addHierarchy(n,cd,cd->isVisited());
+ cd->setVisited(TRUE);
+ }
+ }
+ }
+}
+
+DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::CompoundType ct)
+ : m_prefix(prefix)
+ , m_classType(ct)
+{
+ m_rootNodes = new QList<DotNode>;
+ m_usedNodes = new QDict<DotNode>(1009);
+ m_usedNodes->setAutoDelete(TRUE);
+ m_rootSubgraphs = new DotNodeList;
+
+ // build a graph with each class as a node and the inheritance relations
+ // as edges
+ initClassHierarchy(Doxygen::classSDict);
+ initClassHierarchy(Doxygen::hiddenClasses);
+ addClassList(Doxygen::classSDict);
+ addClassList(Doxygen::hiddenClasses);
+ // m_usedNodes now contains all nodes in the graph
+
+ // color the graph into a set of independent subgraphs
+ bool done=FALSE;
+ int curColor=0;
+ QListIterator<DotNode> dnli(*m_rootNodes);
+ while (!done) // there are still nodes to color
+ {
+ DotNode *n;
+ done=TRUE; // we are done unless there are still uncolored nodes
+ for (dnli.toLast();(n=dnli.current());--dnli)
+ {
+ if (n->subgraphId()==-1) // not yet colored
+ {
+ //printf("Starting at node %s (%p): %d\n",n->label().data(),n,curColor);
+ done=FALSE; // still uncolored nodes
+ n->setSubgraphId(curColor);
+ n->markAsVisible();
+ n->colorConnectedNodes(curColor);
+ curColor++;
+ const DotNode *dn=n->findDocNode();
+ if (dn!=0)
+ m_rootSubgraphs->inSort(dn);
+ else
+ m_rootSubgraphs->inSort(n);
+ }
+ }
+ }
+
+ //printf("Number of independent subgraphs: %d\n",curColor);
+ QListIterator<DotNode> dnli2(*m_rootSubgraphs);
+ DotNode *n;
+ for (dnli2.toFirst();(n=dnli2.current());++dnli2)
+ {
+ //printf("Node %s color=%d (c=%d,p=%d)\n",
+ // n->label().data(),n->m_subgraphId,
+ // n->children()?n->children()->count():0,
+ // n->parents()?n->parents()->count():0);
+ int number=0;
+ n->renumberNodes(number);
+ }
+}
+
+DotGfxHierarchyTable::~DotGfxHierarchyTable()
+{
+ //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n");
+
+ //QDictIterator<DotNode> di(*m_usedNodes);
+ //DotNode *n;
+ //for (;(n=di.current());++di)
+ //{
+ // printf("Node %p: %s\n",n,n->label().data());
+ //}
+
+ delete m_rootNodes;
+ delete m_usedNodes;
+ delete m_rootSubgraphs;
+}
diff --git a/src/dotgfxhierarchytable.h b/src/dotgfxhierarchytable.h
new file mode 100644
index 0000000..5a5bcad
--- /dev/null
+++ b/src/dotgfxhierarchytable.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTGFXHIERARCHYTABLE_H
+#define DOTGFXHIERARCHYTABLE_H
+
+#include "classdef.h"
+#include "ftextstream.h"
+
+#include "dotgraph.h"
+#include "dotnode.h"
+
+/** Represents a graphical class hierarchy */
+class DotGfxHierarchyTable : public DotGraph
+{
+ public:
+ DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class);
+ ~DotGfxHierarchyTable();
+ void createGraph(DotNode *rootNode,FTextStream &t,const char *path,
+ const char *fileName,int id);
+ void writeGraph(FTextStream &t,const char *path, const char *fileName);
+ const DotNodeList *subGraphs() const { return m_rootSubgraphs; }
+
+ protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+
+ private:
+ void addHierarchy(DotNode *n,const ClassDef *cd,bool hide);
+ void addClassList(const ClassSDict *cl);
+
+ int m_graphId;
+ QCString m_prefix;
+ ClassDef::CompoundType m_classType;
+ QList<DotNode> *m_rootNodes;
+ QDict<DotNode> *m_usedNodes;
+ DotNodeList *m_rootSubgraphs;
+ DotNode * m_rootSubgraphNode;
+};
+
+
+#endif
diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp
new file mode 100644
index 0000000..ca6bcca
--- /dev/null
+++ b/src/dotgraph.cpp
@@ -0,0 +1,400 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "config.h"
+#include "doxygen.h"
+#include "index.h"
+#include "md5.h"
+#include "message.h"
+#include "util.h"
+
+#include "dot.h"
+#include "dotrunner.h"
+#include "dotgraph.h"
+#include "dotnode.h"
+
+#define MAP_CMD "cmapx"
+
+QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot
+int DotGraph::DOT_FONTSIZE; // will be initialized in initDot
+
+/*! Checks if a file "baseName".md5 exists. If so the contents
+* are compared with \a md5. If equal FALSE is returned.
+* The .md5 is created or updated after successful creation of the output file.
+*/
+static bool checkMd5Signature(const QCString &baseName,
+ const QCString &md5)
+{
+ QFile f(baseName+".md5");
+ if (f.open(IO_ReadOnly))
+ {
+ // read checksum
+ QCString md5stored(33);
+ int bytesRead=f.readBlock(md5stored.rawData(),32);
+ md5stored[32]='\0';
+ // compare checksum
+ if (bytesRead==32 && md5==md5stored)
+ {
+ // bail out if equal
+ return FALSE;
+ }
+ }
+ f.close();
+ return TRUE;
+}
+
+static bool checkDeliverables(const QCString &file1,
+ const QCString &file2=QCString())
+{
+ bool file1Ok = TRUE;
+ bool file2Ok = TRUE;
+ if (!file1.isEmpty())
+ {
+ QFileInfo fi(file1);
+ file1Ok = (fi.exists() && fi.size()>0);
+ }
+ if (!file2.isEmpty())
+ {
+ QFileInfo fi(file2);
+ file2Ok = (fi.exists() && fi.size()>0);
+ }
+ return file1Ok && file2Ok;
+}
+
+static void removeDotGraph(const QCString &dotName)
+{
+ if (Config_getBool(DOT_CLEANUP))
+ {
+ QDir d;
+ d.remove(dotName);
+ }
+}
+
+static bool insertMapFile(FTextStream &out,const QCString &mapFile,
+ const QCString &relPath,const QCString &mapLabel)
+{
+ QFileInfo fi(mapFile);
+ if (fi.exists() && fi.size()>0) // reuse existing map file
+ {
+ QGString tmpstr;
+ FTextStream tmpout(&tmpstr);
+ convertMapFile(tmpout,mapFile,relPath,FALSE);
+ if (!tmpstr.isEmpty())
+ {
+ out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl;
+ out << tmpstr;
+ out << "</map>" << endl;
+ }
+ return TRUE;
+ }
+ return FALSE; // no map file yet, need to generate it
+}
+
+//--------------------------------------------------------------------
+
+QCString DotGraph::IMG_EXT;
+
+QCString DotGraph::imgName() const
+{
+ return m_baseName + ((m_graphFormat == GOF_BITMAP) ?
+ ("." + IMG_EXT) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps"));
+}
+
+QCString DotGraph::writeGraph(
+ FTextStream& t, // output stream for the code file (html, ...)
+ GraphOutputFormat gf, // bitmap(png/svg) or ps(eps/pdf)
+ EmbeddedOutputFormat ef, // html, latex, ...
+ const char* path, // output folder
+ const char* fileName, // name of the code file (for code patcher)
+ const char* relPath, // output folder relativ to code file
+ bool generateImageMap, // in case of bitmap, shall there be code generated?
+ int graphId) // number of this graph in the current code, used in svg code
+{
+ m_graphFormat = gf;
+ m_textFormat = ef;
+ m_dir = QDir(path);
+ m_fileName = fileName;
+ m_relPath = relPath;
+ m_generateImageMap = generateImageMap;
+ m_graphId = graphId;
+
+ m_absPath = QCString(m_dir.absPath().data()) + "/";
+ m_baseName = getBaseName();
+
+ computeTheGraph();
+
+ m_regenerate = prepareDotFile();
+
+ if (!m_doNotAddImageToIndex) Doxygen::indexList->addImageFile(imgName());
+
+ generateCode(t);
+
+ return m_baseName;
+}
+
+bool DotGraph::prepareDotFile()
+{
+ if (!m_dir.exists())
+ {
+ err("Output dir %s does not exist!\n", m_dir.path().data()); exit(1);
+ }
+
+ QCString sigStr(33);
+ uchar md5_sig[16];
+ // calculate md5
+ MD5Buffer((const unsigned char*)m_theGraph.data(), m_theGraph.length(), md5_sig);
+ // convert result to a string
+ MD5SigToString(md5_sig, sigStr.rawData(), 33);
+
+ // already queued files are processed again in case the output format has changed
+
+ if (!checkMd5Signature(absBaseName(), sigStr) &&
+ checkDeliverables(absImgName(),
+ m_graphFormat == GOF_BITMAP && m_generateImageMap ? absMapName() : QCString()
+ )
+ )
+ {
+ // all needed files are there
+ removeDotGraph(absDotName());
+ return FALSE;
+ }
+
+ // need to rebuild the image
+
+ // write .dot file because image was new or has changed
+ QFile f(absDotName());
+ if (!f.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",f.name().data());
+ return TRUE;
+ }
+ FTextStream t(&f);
+ t << m_theGraph;
+ f.close();
+
+ if (m_graphFormat == GOF_BITMAP)
+ {
+ // run dot to create a bitmap image
+ DotRunner * dotRun = DotManager::instance()->createRunner(absDotName(), sigStr);
+ dotRun->addJob(Config_getEnum(DOT_IMAGE_FORMAT), absImgName());
+ if (m_generateImageMap) dotRun->addJob(MAP_CMD, absMapName());
+ }
+ else if (m_graphFormat == GOF_EPS)
+ {
+ // run dot to create a .eps image
+ DotRunner *dotRun = DotManager::instance()->createRunner(absDotName(), sigStr);
+ if (Config_getBool(USE_PDFLATEX))
+ {
+ dotRun->addJob("pdf",absImgName());
+ }
+ else
+ {
+ dotRun->addJob("ps",absImgName());
+ }
+ }
+ return TRUE;
+}
+
+void DotGraph::generateCode(FTextStream &t)
+{
+ if (m_graphFormat==GOF_BITMAP && m_textFormat==EOF_DocBook)
+ {
+ t << "<para>" << endl;
+ t << " <informalfigure>" << endl;
+ t << " <mediaobject>" << endl;
+ t << " <imageobject>" << endl;
+ t << " <imagedata";
+ t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << IMG_EXT << "\">";
+ t << "</imagedata>" << endl;
+ t << " </imageobject>" << endl;
+ t << " </mediaobject>" << endl;
+ t << " </informalfigure>" << endl;
+ t << "</para>" << endl;
+ }
+ else if (m_graphFormat==GOF_BITMAP && m_generateImageMap) // produce HTML to include the image
+ {
+ if (IMG_EXT=="svg") // add link to SVG file without map file
+ {
+ if (!m_noDivTag) t << "<div class=\"center\">";
+ if (m_regenerate || !writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file
+ {
+ if (m_regenerate)
+ {
+ DotManager::instance()->addSVGConversion(absImgName(),m_relPath,FALSE,QCString(),m_zoomable,m_graphId);
+ }
+ int mapId = DotManager::instance()->addSVGObject(m_fileName,m_baseName,absImgName(),m_relPath);
+ t << "<!-- SVG " << mapId << " -->" << endl;
+ }
+ if (!m_noDivTag) t << "</div>" << endl;
+ }
+ else // add link to bitmap file with image map
+ {
+ if (!m_noDivTag) t << "<div class=\"center\">";
+ t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << getMapLabel() << "\" alt=\"" << getImgAltText() << "\"/>";
+ if (!m_noDivTag) t << "</div>";
+ t << endl;
+ if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel()))
+ {
+ int mapId = DotManager::instance()->addMap(m_fileName, absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel());
+ t << "<!-- MAP " << mapId << " -->" << endl;
+ }
+ }
+ }
+ else if (m_graphFormat==GOF_EPS) // produce tex to include the .eps image
+ {
+ if (m_regenerate || !writeVecGfxFigure(t,m_baseName,absBaseName()))
+ {
+ int figId = DotManager::instance()->addFigure(m_fileName,m_baseName,absBaseName(),FALSE /*TRUE*/);
+ t << endl << "% FIG " << figId << endl;
+ }
+ }
+}
+
+void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title)
+{
+ t << "digraph ";
+ if (title.isEmpty())
+ {
+ t << "\"Dot Graph\"";
+ }
+ else
+ {
+ t << "\"" << convertToXML(title) << "\"";
+ }
+ t << endl << "{" << endl;
+ if (Config_getBool(INTERACTIVE_SVG)) // insert a comment to force regeneration when this
+ // option is toggled
+ {
+ t << " // INTERACTIVE_SVG=YES\n";
+ }
+ t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size repacement
+ if (Config_getBool(DOT_TRANSPARENT))
+ {
+ t << " bgcolor=\"transparent\";" << endl;
+ }
+ t << " edge [fontname=\"" << DOT_FONTNAME << "\","
+ "fontsize=\"" << DOT_FONTSIZE << "\","
+ "labelfontname=\"" << DOT_FONTNAME << "\","
+ "labelfontsize=\"" << DOT_FONTSIZE << "\"];\n";
+ t << " node [fontname=\"" << DOT_FONTNAME << "\","
+ "fontsize=\"" << DOT_FONTSIZE << "\",shape=record];\n";
+}
+
+void DotGraph::writeGraphFooter(FTextStream &t)
+{
+ t << "}" << endl;
+}
+
+void DotGraph::computeGraph(DotNode *root,
+ GraphType gt,
+ GraphOutputFormat format,
+ const QCString &rank, // either "LR", "RL", or ""
+ bool renderParents,
+ bool backArrows,
+ const QCString &title,
+ QGString &graphStr)
+{
+ //printf("computeMd5Signature\n");
+ QGString buf;
+ FTextStream md5stream(&buf);
+ writeGraphHeader(md5stream,title);
+ if (!rank.isEmpty())
+ {
+ md5stream << " rankdir=\"" << rank << "\";" << endl;
+ }
+ root->clearWriteFlag();
+ root->write(md5stream, gt, format, gt!=CallGraph && gt!=Dependency, TRUE, backArrows);
+ if (renderParents && root->parents())
+ {
+ QListIterator<DotNode> dnli(*root->parents());
+ const DotNode *pn;
+ for (dnli.toFirst();(pn=dnli.current());++dnli)
+ {
+ if (pn->isVisible())
+ {
+ root->writeArrow(md5stream, // stream
+ gt, // graph type
+ format, // output format
+ pn, // child node
+ pn->edgeInfo()->at(pn->children()->findRef(root)), // edge info
+ FALSE, // topDown?
+ backArrows // point back?
+ );
+ }
+ pn->write(md5stream, // stream
+ gt, // graph type
+ format, // output format
+ TRUE, // topDown?
+ FALSE, // toChildren?
+ backArrows // backward pointing arrows?
+ );
+ }
+ }
+ writeGraphFooter(md5stream);
+
+ graphStr=buf.data();
+}
+
+bool DotGraph::writeVecGfxFigure(FTextStream &out,const QCString &baseName,
+ const QCString &figureName)
+{
+ int width=400,height=550;
+ if (Config_getBool(USE_PDFLATEX))
+ {
+ if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE))
+ {
+ //printf("writeVecGfxFigure()=0\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE))
+ {
+ //printf("writeVecGfxFigure()=0\n");
+ return FALSE;
+ }
+ }
+ //printf("Got PDF/EPS size %d,%d\n",width,height);
+ int maxWidth = 350; /* approx. page width in points, excl. margins */
+ int maxHeight = 550; /* approx. page height in points, excl. margins */
+ out << "\\nopagebreak\n"
+ "\\begin{figure}[H]\n"
+ "\\begin{center}\n"
+ "\\leavevmode\n";
+ if (width>maxWidth || height>maxHeight) // figure too big for page
+ {
+ // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0
+ if (width*maxHeight>height*maxWidth)
+ {
+ out << "\\includegraphics[width=" << maxWidth << "pt]";
+ }
+ else
+ {
+ out << "\\includegraphics[height=" << maxHeight << "pt]";
+ }
+ }
+ else
+ {
+ out << "\\includegraphics[width=" << width << "pt]";
+ }
+
+ out << "{" << baseName << "}\n"
+ "\\end{center}\n"
+ "\\end{figure}\n";
+
+ //printf("writeVecGfxFigure()=1\n");
+ return TRUE;
+}
diff --git a/src/dotgraph.h b/src/dotgraph.h
new file mode 100644
index 0000000..27d6938
--- /dev/null
+++ b/src/dotgraph.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1997-2019 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.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ */
+
+#ifndef DOTGRAPH_H
+#define DOTGRAPH_H
+
+#include <qcstring.h>
+#include <qgstring.h>
+#include <qdir.h>
+
+class FTextStream;
+class DotNode;
+
+enum GraphOutputFormat { GOF_BITMAP, GOF_EPS };
+enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook };
+enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph };
+
+/** A dot graph */
+class DotGraph
+{
+ public:
+ DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {}
+ virtual ~DotGraph() {}
+
+ static QCString DOT_FONTNAME; // will be initialized in initDot
+ static int DOT_FONTSIZE; // will be initialized in initDot
+
+ static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, const QCString& figureName);
+
+ protected:
+ /** returns node numbers. The Counter is reset by the constructor */
+ int getNextNodeNumber() { return ++m_curNodeNumber; }
+
+ QCString writeGraph(FTextStream &t,
+ GraphOutputFormat gf,
+ EmbeddedOutputFormat ef,
+ const char *path,
+ const char *fileName,
+ const char *relPath,
+ bool writeImageMap=TRUE,
+ int graphId=-1
+ );
+
+ static void writeGraphHeader(FTextStream& t, const QCString& title = QCString());
+ static void writeGraphFooter(FTextStream& t);
+ static void computeGraph(DotNode* root,
+ GraphType gt,
+ GraphOutputFormat format,
+ const QCString& rank, // either "LR", "RL", or ""
+ bool renderParents,
+ bool backArrows,
+ const QCString& title,
+ QGString& graphStr
+ );
+
+ virtual QCString getBaseName() const = 0;
+ virtual QCString absMapName() const { return m_absPath + m_baseName + ".map"; }
+ virtual QCString getMapLabel() const = 0;
+ virtual QCString getImgAltText() const { return ""; }
+
+ virtual void computeTheGraph() = 0;
+
+ static QCString IMG_EXT;
+
+ friend void initDot();
+
+ QCString absBaseName() const { return m_absPath + m_baseName; }
+ QCString absDotName() const { return m_absPath + m_baseName + ".dot"; }
+ QCString imgName() const;
+ QCString absImgName() const { return m_absPath + imgName(); }
+ QCString relImgName() const { return m_relPath + imgName(); }
+
+ // the following variables are used while writing the graph to a .dot file
+ GraphOutputFormat m_graphFormat;
+ EmbeddedOutputFormat m_textFormat;
+ QDir m_dir;
+ QCString m_fileName;
+ QCString m_relPath;
+ bool m_generateImageMap;
+ int m_graphId;
+
+ QCString m_absPath;
+ QCString m_baseName;
+ QGString m_theGraph;
+ bool m_regenerate;
+ bool m_doNotAddImageToIndex;
+ bool m_noDivTag;
+ bool m_zoomable;
+ bool m_urlOnly;
+
+ private:
+ DotGraph(const DotGraph &);
+ DotGraph &operator=(const DotGraph &);
+
+ bool prepareDotFile();
+ void generateCode(FTextStream &t);
+
+ int m_curNodeNumber;
+};
+
+#endif
diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp
new file mode 100644
index 0000000..be55ac0
--- /dev/null
+++ b/src/dotgroupcollaboration.cpp
@@ -0,0 +1,381 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotgroupcollaboration.h"
+
+#include "dotnode.h"
+#include "classlist.h"
+#include "doxygen.h"
+#include "namespacedef.h"
+#include "pagedef.h"
+#include "util.h"
+#include "config.h"
+
+#define DOT_TRANSPARENT Config_getBool(DOT_TRANSPARENT)
+
+DotGroupCollaboration::DotGroupCollaboration(const GroupDef* gd)
+{
+ QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase();
+ m_usedNodes = new QDict<DotNode>(1009);
+ QCString tooltip = gd->briefDescriptionAsTooltip();
+ m_rootNode = new DotNode(getNextNodeNumber(), gd->groupTitle(), tooltip, tmp_url, TRUE );
+ m_rootNode->markAsVisible();
+ m_usedNodes->insert(gd->name(), m_rootNode );
+ m_edges.setAutoDelete(TRUE);
+
+ m_diskName = gd->getOutputFileBase();
+
+ buildGraph( gd );
+}
+
+DotGroupCollaboration::~DotGroupCollaboration()
+{
+ delete m_usedNodes;
+}
+
+void DotGroupCollaboration::buildGraph(const GroupDef* gd)
+{
+ QCString tmp_url;
+ //===========================
+ // hierarchy.
+
+ // Write parents
+ const GroupList *groups = gd->partOfGroups();
+ if ( groups )
+ {
+ GroupListIterator gli(*groups);
+ const GroupDef *d;
+ for (gli.toFirst();(d=gli.current());++gli)
+ {
+ DotNode* nnode = m_usedNodes->find(d->name());
+ if ( !nnode )
+ { // add node
+ tmp_url = d->getReference()+"$"+d->getOutputFileBase();
+ QCString tooltip = d->briefDescriptionAsTooltip();
+ nnode = new DotNode(getNextNodeNumber(), d->groupTitle(), tooltip, tmp_url );
+ nnode->markAsVisible();
+ m_usedNodes->insert(d->name(), nnode );
+ }
+ tmp_url = "";
+ addEdge( nnode, m_rootNode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
+ }
+ }
+
+ // Add subgroups
+ if ( gd->getSubGroups() && gd->getSubGroups()->count() )
+ {
+ QListIterator<GroupDef> defli(*gd->getSubGroups());
+ const GroupDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ DotNode* nnode = m_usedNodes->find(def->name());
+ if ( !nnode )
+ { // add node
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase();
+ QCString tooltip = def->briefDescriptionAsTooltip();
+ nnode = new DotNode(getNextNodeNumber(), def->groupTitle(), tooltip, tmp_url );
+ nnode->markAsVisible();
+ m_usedNodes->insert(def->name(), nnode );
+ }
+ tmp_url = "";
+ addEdge( m_rootNode, nnode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url );
+ }
+ }
+
+ //=======================
+ // Write collaboration
+
+ // Add members
+ addMemberList( gd->getMemberList(MemberListType_allMembersList) );
+
+ // Add classes
+ if ( gd->getClasses() && gd->getClasses()->count() )
+ {
+ ClassSDict::Iterator defli(*gd->getClasses());
+ ClassDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+ if (!def->anchor().isEmpty())
+ {
+ tmp_url+="#"+def->anchor();
+ }
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass );
+ }
+ }
+
+ // Add namespaces
+ if ( gd->getNamespaces() && gd->getNamespaces()->count() )
+ {
+ NamespaceSDict::Iterator defli(*gd->getNamespaces());
+ NamespaceDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace );
+ }
+ }
+
+ // Add files
+ if ( gd->getFiles() && gd->getFiles()->count() )
+ {
+ QListIterator<FileDef> defli(*gd->getFiles());
+ const FileDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile );
+ }
+ }
+
+ // Add pages
+ if ( gd->getPages() && gd->getPages()->count() )
+ {
+ PageSDict::Iterator defli(*gd->getPages());
+ PageDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages );
+ }
+ }
+
+ // Add directories
+ if ( gd->getDirs() && gd->getDirs()->count() )
+ {
+ QListIterator<DirDef> defli(*gd->getDirs());
+ const DirDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension;
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir );
+ }
+ }
+}
+
+void DotGroupCollaboration::addMemberList( MemberList* ml )
+{
+ if ( !( ml && ml->count()) ) return;
+ MemberListIterator defli(*ml);
+ MemberDef *def;
+ for (;(def=defli.current());++defli)
+ {
+ QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension
+ +"#"+def->anchor();
+ addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember );
+ }
+}
+
+DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge(
+ DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
+ const QCString& _label, const QCString& _url )
+{
+ // search a existing link.
+ QListIterator<Edge> lli(m_edges);
+ Edge* newEdge = 0;
+ for ( lli.toFirst(); (newEdge=lli.current()); ++lli)
+ {
+ if ( newEdge->pNStart==_pNStart &&
+ newEdge->pNEnd==_pNEnd &&
+ newEdge->eType==_eType
+ )
+ { // edge already found
+ break;
+ }
+ }
+ if ( newEdge==0 ) // new link
+ {
+ newEdge = new Edge(_pNStart,_pNEnd,_eType);
+ m_edges.append( newEdge );
+ }
+
+ if (!_label.isEmpty())
+ {
+ newEdge->links.append(new Link(_label,_url));
+ }
+
+ return newEdge;
+}
+
+void DotGroupCollaboration::addCollaborationMember(
+ const Definition* def, QCString& url, EdgeType eType )
+{
+ // Create group nodes
+ if ( !def->partOfGroups() )
+ return;
+ GroupListIterator gli(*def->partOfGroups());
+ GroupDef *d;
+ QCString tmp_str;
+ for (;(d=gli.current());++gli)
+ {
+ DotNode* nnode = m_usedNodes->find(d->name());
+ if ( nnode != m_rootNode )
+ {
+ if ( nnode==0 )
+ { // add node
+ tmp_str = d->getReference()+"$"+d->getOutputFileBase();
+ QCString tooltip = d->briefDescriptionAsTooltip();
+ nnode = new DotNode(getNextNodeNumber(), d->groupTitle(), tooltip, tmp_str );
+ nnode->markAsVisible();
+ m_usedNodes->insert(d->name(), nnode );
+ }
+ tmp_str = def->qualifiedName();
+ addEdge( m_rootNode, nnode, eType, tmp_str, url );
+ }
+ }
+}
+
+QCString DotGroupCollaboration::getBaseName() const
+{
+ return m_diskName;
+}
+
+void DotGroupCollaboration::computeTheGraph()
+{
+ FTextStream md5stream(&m_theGraph);
+ writeGraphHeader(md5stream,m_rootNode->label());
+
+ // clean write flags
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *pn;
+ for (dni.toFirst();(pn=dni.current());++dni)
+ {
+ pn->clearWriteFlag();
+ }
+
+ // write other nodes.
+ for (dni.toFirst();(pn=dni.current());++dni)
+ {
+ pn->write(md5stream,Inheritance,m_graphFormat,TRUE,FALSE,FALSE);
+ }
+
+ // write edges
+ QListIterator<Edge> eli(m_edges);
+ Edge* edge;
+ for (eli.toFirst();(edge=eli.current());++eli)
+ {
+ edge->write( md5stream );
+ }
+
+ writeGraphFooter(md5stream);
+
+}
+
+QCString DotGroupCollaboration::getMapLabel() const
+{
+ return escapeCharsInString(m_baseName, FALSE);
+}
+
+QCString DotGroupCollaboration::writeGraph( FTextStream &t,
+ GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat,
+ const char *path, const char *fileName, const char *relPath,
+ bool generateImageMap,int graphId)
+{
+ m_doNotAddImageToIndex = TRUE;
+
+ return DotGraph::writeGraph(t, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId);
+}
+
+void DotGroupCollaboration::Edge::write( FTextStream &t ) const
+{
+ const char* linkTypeColor[] = {
+ "darkorchid3"
+ ,"orange"
+ ,"blueviolet"
+ ,"darkgreen"
+ ,"firebrick4"
+ ,"grey75"
+ ,"midnightblue"
+ };
+ QCString arrowStyle = "dir=\"none\", style=\"dashed\"";
+ t << " Node" << pNStart->number();
+ t << "->";
+ t << "Node" << pNEnd->number();
+
+ t << " [shape=plaintext";
+ if (links.count()>0) // there are links
+ {
+ t << ", ";
+ // HTML-like edge labels crash on my Mac with Graphviz 2.0! and
+ // are not supported by older version of dot.
+ //
+ //t << label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">";
+ //QListIterator<Link> lli(links);
+ //Link *link;
+ //for( lli.toFirst(); (link=lli.current()); ++lli)
+ //{
+ // t << "<TR><TD";
+ // if ( !link->url.isEmpty() )
+ // t << " HREF=\"" << link->url << "\"";
+ // t << ">" << link->label << "</TD></TR>";
+ //}
+ //t << "</TABLE>>";
+
+ t << "label=\"";
+ QListIterator<Link> lli(links);
+ Link *link;
+ bool first=TRUE;
+ int count=0;
+ const int maxLabels = 10;
+ for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count)
+ {
+ if (first) first=FALSE; else t << "\\n";
+ t << DotNode::convertLabel(link->label);
+ }
+ if (count==maxLabels) t << "\\n...";
+ t << "\"";
+
+ }
+ switch( eType )
+ {
+ case thierarchy:
+ arrowStyle = "dir=\"back\", style=\"solid\"";
+ break;
+ default:
+ t << ", color=\"" << linkTypeColor[(int)eType] << "\"";
+ break;
+ }
+ t << ", " << arrowStyle;
+ t << "];" << endl;
+}
+
+bool DotGroupCollaboration::isTrivial() const
+{
+ return m_usedNodes->count() <= 1;
+}
+
+void DotGroupCollaboration::writeGraphHeader(FTextStream &t,
+ const QCString &title) const
+{
+ t << "digraph ";
+ if (title.isEmpty())
+ {
+ t << "\"Dot Graph\"";
+ }
+ else
+ {
+ t << "\"" << convertToXML(title) << "\"";
+ }
+ t << endl;
+ t << "{" << endl;
+ if (DOT_TRANSPARENT)
+ {
+ t << " bgcolor=\"transparent\";" << endl;
+ }
+ t << " edge [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\","
+ "labelfontname=\"" << DOT_FONTNAME << "\",labelfontsize=\"" << DOT_FONTSIZE << "\"];\n";
+ t << " node [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\",shape=box];\n";
+ t << " rankdir=LR;\n";
+}
diff --git a/src/dotgroupcollaboration.h b/src/dotgroupcollaboration.h
new file mode 100644
index 0000000..539637f
--- /dev/null
+++ b/src/dotgroupcollaboration.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTGROUPCOLLABORATION_H
+#define DOTGROUPCOLLABORATION_H
+
+#include "dotgraph.h"
+#include "qlist.h"
+#include "groupdef.h"
+
+/** Representation of a group collaboration graph */
+class DotGroupCollaboration : public DotGraph
+{
+ public :
+ DotGroupCollaboration(const GroupDef* gd);
+ ~DotGroupCollaboration();
+ QCString writeGraph(FTextStream &t, GraphOutputFormat gf,EmbeddedOutputFormat ef,
+ const char *path,const char *fileName,const char *relPath,
+ bool writeImageMap=TRUE,int graphId=-1);
+ bool isTrivial() const;
+
+ protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+
+ private :
+ enum EdgeType
+ {
+ tmember = 0,
+ tclass,
+ tnamespace,
+ tfile,
+ tpages,
+ tdir,
+ thierarchy
+ };
+
+ struct Link
+ {
+ Link(const QCString lab,const QCString &u) : label(lab), url(u) {}
+ QCString label;
+ QCString url;
+ };
+
+ struct Edge
+ {
+ Edge(DotNode *start,DotNode *end,EdgeType type)
+ : pNStart(start), pNEnd(end), eType(type)
+ { links.setAutoDelete(TRUE); }
+
+ DotNode* pNStart;
+ DotNode* pNEnd;
+ EdgeType eType;
+
+ QList<Link> links;
+ void write( FTextStream &t ) const;
+ };
+
+ void buildGraph(const GroupDef* gd);
+ void addCollaborationMember(const Definition* def, QCString& url, EdgeType eType );
+ void addMemberList( class MemberList* ml );
+ void writeGraphHeader(FTextStream &t,const QCString &title) const;
+ Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
+ const QCString& _label, const QCString& _url );
+
+ DotNode *m_rootNode;
+ QDict<DotNode> *m_usedNodes;
+ QCString m_diskName;
+ QList<Edge> m_edges;
+};
+
+#endif
diff --git a/src/dotincldepgraph.cpp b/src/dotincldepgraph.cpp
new file mode 100644
index 0000000..c968b68
--- /dev/null
+++ b/src/dotincldepgraph.cpp
@@ -0,0 +1,238 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotincldepgraph.h"
+#include "dotnode.h"
+#include "util.h"
+#include "config.h"
+
+void DotInclDepGraph::buildGraph(DotNode *n,const FileDef *fd,int distance)
+{
+ QList<IncludeInfo> *includeFiles = m_inverse ? fd->includedByFileList() : fd->includeFileList();
+ if (includeFiles)
+ {
+ QListIterator<IncludeInfo> ili(*includeFiles);
+ IncludeInfo *ii;
+ for (;(ii=ili.current());++ili)
+ {
+ const FileDef *bfd = ii->fileDef;
+ QCString in = ii->includeName;
+ //printf(">>>> in=`%s' bfd=%p\n",ii->includeName.data(),bfd);
+ bool doc=TRUE,src=FALSE;
+ if (bfd)
+ {
+ in = bfd->absFilePath();
+ doc = bfd->isLinkable() && !bfd->isHidden();
+ src = bfd->generateSourceFile();
+ }
+ if (doc || src || !Config_getBool(HIDE_UNDOC_RELATIONS))
+ {
+ QCString url="";
+ if (bfd) url=bfd->getOutputFileBase().copy();
+ if (!doc && src)
+ {
+ url=bfd->getSourceFileBase();
+ }
+ DotNode *bn = m_usedNodes->find(in);
+ if (bn) // file is already a node in the graph
+ {
+ n->addChild(bn,0,0,0);
+ bn->addParent(n);
+ bn->setDistance(distance);
+ }
+ else
+ {
+ QCString tmp_url;
+ QCString tooltip;
+ if (bfd)
+ {
+ tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString();
+ tooltip = bfd->briefDescriptionAsTooltip();
+ }
+ bn = new DotNode(getNextNodeNumber(),// n
+ ii->includeName, // label
+ tooltip, // tip
+ tmp_url, // url
+ FALSE, // rootNode
+ 0); // cd
+ n->addChild(bn,0,0,0);
+ bn->addParent(n);
+ m_usedNodes->insert(in,bn);
+ bn->setDistance(distance);
+
+ if (bfd) buildGraph(bn,bfd,distance+1);
+ }
+ }
+ }
+ }
+}
+
+void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes)
+{
+ while (queue.count()>0 && maxNodes>0)
+ {
+ DotNode *n = queue.take(0);
+ if (!n->isVisible() && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed
+ {
+ n->markAsVisible();
+ maxNodes--;
+ // add direct children
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ queue.append(dn);
+ }
+ }
+ }
+ }
+}
+
+void DotInclDepGraph::determineTruncatedNodes(QList<DotNode> &queue)
+{
+ while (queue.count()>0)
+ {
+ DotNode *n = queue.take(0);
+ if (n->isVisible() && n->isTruncated()==DotNode::Unknown)
+ {
+ bool truncated = FALSE;
+ if (n->children())
+ {
+ QListIterator<DotNode> li(*n->children());
+ const DotNode *dn;
+ for (li.toFirst();(dn=li.current());++li)
+ {
+ if (!dn->isVisible())
+ {
+ truncated = TRUE;
+ }
+ else
+ {
+ queue.append(dn);
+ }
+ }
+ }
+ n->markAsTruncated(truncated);
+ }
+ }
+}
+
+DotInclDepGraph::DotInclDepGraph(const FileDef *fd,bool inverse)
+{
+ m_inverse = inverse;
+ ASSERT(fd!=0);
+ m_inclDepFileName = fd->includeDependencyGraphFileName();
+ m_inclByDepFileName = fd->includedByDependencyGraphFileName();
+ QCString tmp_url=fd->getReference()+"$"+fd->getOutputFileBase();
+ QCString tooltip = fd->briefDescriptionAsTooltip();
+ m_startNode = new DotNode(getNextNodeNumber(),
+ fd->docName(),
+ tooltip,
+ tmp_url.data(),
+ TRUE); // root node
+ m_startNode->setDistance(0);
+ m_usedNodes = new QDict<DotNode>(1009);
+ m_usedNodes->insert(fd->absFilePath(),m_startNode);
+ buildGraph(m_startNode,fd,1);
+
+ int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES);
+ QList<DotNode> openNodeQueue;
+ openNodeQueue.append(m_startNode);
+ determineVisibleNodes(openNodeQueue,maxNodes);
+ openNodeQueue.clear();
+ openNodeQueue.append(m_startNode);
+ determineTruncatedNodes(openNodeQueue);
+}
+
+DotInclDepGraph::~DotInclDepGraph()
+{
+ DotNode::deleteNodes(m_startNode);
+ delete m_usedNodes;
+}
+
+QCString DotInclDepGraph::getBaseName() const
+{
+ if (m_inverse)
+ {
+ return m_inclByDepFileName;
+ }
+ else
+ {
+ return m_inclDepFileName;
+ }
+}
+
+void DotInclDepGraph::computeTheGraph()
+{
+ computeGraph(m_startNode, Dependency, m_graphFormat, "", FALSE,
+ m_inverse, m_startNode->label(), m_theGraph);
+}
+
+QCString DotInclDepGraph::getMapLabel() const
+{
+ if (m_inverse)
+ {
+ return escapeCharsInString(m_startNode->label(),FALSE) + "dep";
+ }
+ else
+ {
+ return escapeCharsInString(m_startNode->label(),FALSE);
+ }
+}
+
+QCString DotInclDepGraph::writeGraph(FTextStream &out,
+ GraphOutputFormat graphFormat,
+ EmbeddedOutputFormat textFormat,
+ const char *path,
+ const char *fileName,
+ const char *relPath,
+ bool generateImageMap,
+ int graphId)
+{
+ return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId);
+}
+
+bool DotInclDepGraph::isTrivial() const
+{
+ return m_startNode->children()==0;
+}
+
+bool DotInclDepGraph::isTooBig() const
+{
+ int numNodes = m_startNode->children() ? m_startNode->children()->count() : 0;
+ return numNodes>=Config_getInt(DOT_GRAPH_MAX_NODES);
+}
+
+void DotInclDepGraph::writeXML(FTextStream &t)
+{
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *node;
+ for (;(node=dni.current());++dni)
+ {
+ node->writeXML(t,FALSE);
+ }
+}
+
+void DotInclDepGraph::writeDocbook(FTextStream &t)
+{
+ QDictIterator<DotNode> dni(*m_usedNodes);
+ DotNode *node;
+ for (;(node=dni.current());++dni)
+ {
+ node->writeDocbook(t,FALSE);
+ }
+}
diff --git a/src/dotincldepgraph.h b/src/dotincldepgraph.h
new file mode 100644
index 0000000..b664ccb
--- /dev/null
+++ b/src/dotincldepgraph.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTINCLDEPGRAPH_H
+#define DOTINCLDEPGRAPH_H
+
+#include "qcstring.h"
+#include "filedef.h"
+
+#include "dotgraph.h"
+
+/** Representation of an include dependency graph */
+class DotInclDepGraph : public DotGraph
+{
+ public:
+ DotInclDepGraph(const FileDef *fd,bool inverse);
+ ~DotInclDepGraph();
+ QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef,
+ const char *path,const char *fileName,const char *relPath,
+ bool writeImageMap=TRUE,int graphId=-1);
+ bool isTrivial() const;
+ bool isTooBig() const;
+ void writeXML(FTextStream &t);
+ void writeDocbook(FTextStream &t);
+
+ protected:
+ virtual QCString getBaseName() const;
+ virtual QCString getMapLabel() const;
+ virtual void computeTheGraph();
+
+ private:
+ QCString diskName() const;
+ void buildGraph(DotNode *n,const FileDef *fd,int distance);
+ void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes);
+ void determineTruncatedNodes(QList<DotNode> &queue);
+
+ DotNode *m_startNode;
+ QDict<DotNode> *m_usedNodes;
+ QCString m_inclDepFileName;
+ QCString m_inclByDepFileName;
+ bool m_inverse;
+};
+
+#endif
diff --git a/src/dotnode.cpp b/src/dotnode.cpp
new file mode 100644
index 0000000..41d5f06
--- /dev/null
+++ b/src/dotnode.cpp
@@ -0,0 +1,950 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotnode.h"
+
+#include "ftextstream.h"
+#include "classdef.h"
+#include "config.h"
+#include "memberlist.h"
+#include "membergroup.h"
+#include "language.h"
+#include "doxygen.h"
+#include "util.h"
+
+/** Helper struct holding the properties of a edge in a dot graph. */
+struct EdgeProperties
+{
+ const char * const *edgeColorMap;
+ const char * const *arrowStyleMap;
+ const char * const *edgeStyleMap;
+};
+
+/*! mapping from protection levels to color names */
+static const char *normalEdgeColorMap[] =
+{
+ "midnightblue", // Public
+ "darkgreen", // Protected
+ "firebrick4", // Private
+ "darkorchid3", // "use" relation
+ "grey75", // Undocumented
+ "orange", // template relation
+ "orange" // type constraint
+};
+
+static const char *normalArrowStyleMap[] =
+{
+ "empty", // Public
+ "empty", // Protected
+ "empty", // Private
+ "open", // "use" relation
+ 0, // Undocumented
+ 0 // template relation
+};
+
+static const char *normalEdgeStyleMap[] =
+{
+ "solid", // inheritance
+ "dashed" // usage
+};
+
+static const char *umlEdgeColorMap[] =
+{
+ "midnightblue", // Public
+ "darkgreen", // Protected
+ "firebrick4", // Private
+ "grey25", // "use" relation
+ "grey75", // Undocumented
+ "orange", // template relation
+ "orange" // type constraint
+};
+
+static const char *umlArrowStyleMap[] =
+{
+ "onormal", // Public
+ "onormal", // Protected
+ "onormal", // Private
+ "odiamond", // "use" relation
+ 0, // Undocumented
+ 0 // template relation
+};
+
+static const char *umlEdgeStyleMap[] =
+{
+ "solid", // inheritance
+ "solid" // usage
+};
+
+static EdgeProperties normalEdgeProps =
+{
+ normalEdgeColorMap, normalArrowStyleMap, normalEdgeStyleMap
+};
+
+static EdgeProperties umlEdgeProps =
+{
+ umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap
+};
+
+static QCString escapeTooltip(const QCString &tooltip)
+{
+ QCString result;
+ const char *p=tooltip.data();
+ if (p==0) return result;
+ char c;
+ while ((c=*p++))
+ {
+ switch(c)
+ {
+ case '"': result+="\\\""; break;
+ case '\\': result+="\\\\"; break;
+ default: result+=c; break;
+ }
+ }
+ return result;
+}
+
+static void writeBoxMemberList(FTextStream &t,
+ char prot,MemberList *ml,const ClassDef *scope,
+ bool isStatic=FALSE,const QDict<void> *skipNames=0)
+{
+ (void)isStatic;
+ if (ml)
+ {
+ MemberListIterator mlia(*ml);
+ MemberDef *mma;
+ int totalCount=0;
+ for (mlia.toFirst();(mma = mlia.current());++mlia)
+ {
+ if (mma->getClassDef()==scope &&
+ (skipNames==0 || skipNames->find(mma->name())==0))
+ {
+ totalCount++;
+ }
+ }
+
+ int count=0;
+ for (mlia.toFirst();(mma = mlia.current());++mlia)
+ {
+ if (mma->getClassDef() == scope &&
+ (skipNames==0 || skipNames->find(mma->name())==0))
+ {
+ int numFields = Config_getInt(UML_LIMIT_NUM_FIELDS);
+ if (numFields>0 && (totalCount>numFields*3/2 && count>=numFields))
+ {
+ t << theTranslator->trAndMore(QCString().sprintf("%d",totalCount-count)) << "\\l";
+ break;
+ }
+ else
+ {
+ t << prot << " ";
+ t << DotNode::convertLabel(mma->name());
+ if (!mma->isObjCMethod() &&
+ (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()";
+ t << "\\l";
+ count++;
+ }
+ }
+ }
+ // write member groups within the memberlist
+ MemberGroupList *mgl = ml->getMemberGroupList();
+ if (mgl)
+ {
+ MemberGroupListIterator mgli(*mgl);
+ MemberGroup *mg;
+ for (mgli.toFirst();(mg=mgli.current());++mgli)
+ {
+ if (mg->members())
+ {
+ writeBoxMemberList(t,prot,mg->members(),scope,isStatic,skipNames);
+ }
+ }
+ }
+ }
+}
+
+QCString DotNode::convertLabel(const QCString &l)
+{
+ QString bBefore("\\_/<({[: =-+@%#~?$"); // break before character set
+ QString bAfter(">]),:;|"); // break after character set
+ QString p(l);
+ if (p.isEmpty()) return QCString();
+ QString result;
+ QChar c,pc=0;
+ uint idx = 0;
+ int len=p.length();
+ int charsLeft=len;
+ int sinceLast=0;
+ int foldLen=17; // ideal text length
+ while (idx < p.length())
+ {
+ c = p[idx++];
+ QString replacement;
+ switch(c)
+ {
+ case '\\': replacement="\\\\"; break;
+ case '\n': replacement="\\n"; break;
+ case '<': replacement="\\<"; break;
+ case '>': replacement="\\>"; break;
+ case '|': replacement="\\|"; break;
+ case '{': replacement="\\{"; break;
+ case '}': replacement="\\}"; break;
+ case '"': replacement="\\\""; break;
+ default: replacement=c; break;
+ }
+ // Some heuristics to insert newlines to prevent too long
+ // boxes and at the same time prevent ugly breaks
+ if (c=='\n')
+ {
+ result+=replacement;
+ foldLen = (3*foldLen+sinceLast+2)/4;
+ sinceLast=1;
+ }
+ else if ((pc!=':' || c!=':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.contains(c))
+ {
+ result+="\\l";
+ result+=replacement;
+ foldLen = (foldLen+sinceLast+1)/2;
+ sinceLast=1;
+ }
+ else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 &&
+ !isupper(c) && p[idx].category()==QChar::Letter_Uppercase)
+ {
+ result+=replacement;
+ result+="\\l";
+ foldLen = (foldLen+sinceLast+1)/2;
+ sinceLast=0;
+ }
+ else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.contains(c) && (c!=':' || p[idx]!=':'))
+ {
+ result+=replacement;
+ result+="\\l";
+ foldLen = (foldLen+sinceLast+1)/2;
+ sinceLast=0;
+ }
+ else
+ {
+ result+=replacement;
+ sinceLast++;
+ }
+ charsLeft--;
+ pc=c;
+ }
+ return result.utf8();
+}
+
+static QCString stripProtectionPrefix(const QCString &s)
+{
+ if (!s.isEmpty() && (s[0]=='-' || s[0]=='+' || s[0]=='~' || s[0]=='#'))
+ {
+ return s.mid(1);
+ }
+ else
+ {
+ return s;
+ }
+}
+
+DotNode::DotNode(int n,const char *lab,const char *tip, const char *url,
+ bool isRoot,const ClassDef *cd)
+ : m_subgraphId(-1)
+ , m_number(n)
+ , m_label(lab)
+ , m_tooltip(tip)
+ , m_url(url)
+ , m_parents(0)
+ , m_children(0)
+ , m_edgeInfo(0)
+ , m_deleted(FALSE)
+ , m_written(FALSE)
+ , m_hasDoc(FALSE)
+ , m_isRoot(isRoot)
+ , m_classDef(cd)
+ , m_visible(FALSE)
+ , m_truncated(Unknown)
+ , m_distance(1000)
+ , m_renumbered(false)
+{
+}
+
+DotNode::~DotNode()
+{
+ delete m_children;
+ delete m_parents;
+ delete m_edgeInfo;
+}
+
+void DotNode::addChild(DotNode *n,
+ int edgeColor,
+ int edgeStyle,
+ const char *edgeLab,
+ const char *edgeURL,
+ int edgeLabCol
+)
+{
+ if (m_children==0)
+ {
+ m_children = new QList<DotNode>;
+ m_edgeInfo = new QList<EdgeInfo>;
+ m_edgeInfo->setAutoDelete(TRUE);
+ }
+ m_children->append(n);
+ EdgeInfo *ei = new EdgeInfo(
+ edgeColor,
+ edgeStyle,
+ edgeLab,
+ edgeURL,
+ edgeLabCol==-1 ? edgeColor : edgeLabCol);
+ m_edgeInfo->append(ei);
+}
+
+void DotNode::addParent(DotNode *n)
+{
+ if (m_parents==0)
+ {
+ m_parents = new QList<DotNode>;
+ }
+ m_parents->append(n);
+}
+
+void DotNode::removeChild(DotNode *n)
+{
+ if (m_children) m_children->remove(n);
+}
+
+void DotNode::removeParent(DotNode *n)
+{
+ if (m_parents) m_parents->remove(n);
+}
+
+void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes)
+{
+ if (m_deleted) return; // avoid recursive loops in case the graph has cycles
+ m_deleted=TRUE;
+ if (m_parents!=0) // delete all parent nodes of this node
+ {
+ QListIterator<DotNode> dnlip(*m_parents);
+ DotNode *pn;
+ for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
+ {
+ //pn->removeChild(this);
+ pn->deleteNode(deletedList,skipNodes);
+ }
+ }
+ if (m_children!=0) // delete all child nodes of this node
+ {
+ QListIterator<DotNode> dnlic(*m_children);
+ DotNode *cn;
+ for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
+ {
+ //cn->removeParent(this);
+ cn->deleteNode(deletedList,skipNodes);
+ }
+ }
+ // add this node to the list of deleted nodes.
+ //printf("skipNodes=%p find(%p)=%p\n",skipNodes,this,skipNodes ? skipNodes->find((int)this) : 0);
+ if (skipNodes==0 || skipNodes->find((char*)this)==0)
+ {
+ //printf("deleting\n");
+ deletedList.append(this);
+ }
+}
+
+void DotNode::setDistance(int distance)
+{
+ if (distance<m_distance) m_distance = distance;
+}
+
+inline int DotNode::findParent( DotNode *n )
+{
+ if ( !m_parents ) return -1;
+ return m_parents->find(n);
+}
+
+/*! helper function that deletes all nodes in a connected graph, given
+* one of the graph's nodes
+*/
+void DotNode::deleteNodes(DotNode *node,SDict<DotNode> *skipNodes)
+{
+ //printf("deleteNodes skipNodes=%p\n",skipNodes);
+ static DotNodeList deletedNodes;
+ deletedNodes.setAutoDelete(TRUE);
+ node->deleteNode(deletedNodes,skipNodes); // collect nodes to be deleted.
+ deletedNodes.clear(); // actually remove the nodes.
+}
+
+void DotNode::writeBox(FTextStream &t,
+ GraphType gt,
+ GraphOutputFormat /*format*/,
+ bool hasNonReachableChildren) const
+{
+ const char *labCol =
+ m_url.isEmpty() ? "grey75" : // non link
+ (hasNonReachableChildren ? "red" : "black");
+ t << " Node" << m_number << " [label=\"";
+
+ if (m_classDef && Config_getBool(UML_LOOK) && (gt==Inheritance || gt==Collaboration))
+ {
+ // add names shown as relations to a dictionary, so we don't show
+ // them as attributes as well
+ QDict<void> arrowNames(17);
+ if (m_edgeInfo)
+ {
+ // for each edge
+ QListIterator<EdgeInfo> li(*m_edgeInfo);
+ EdgeInfo *ei;
+ for (li.toFirst();(ei=li.current());++li)
+ {
+ if (!ei->label().isEmpty()) // labels joined by \n
+ {
+ int li=ei->label().find('\n');
+ int p=0;
+ QCString lab;
+ while ((li=ei->label().find('\n',p))!=-1)
+ {
+ lab = stripProtectionPrefix(ei->label().mid(p,li-p));
+ arrowNames.insert(lab,(void*)0x8);
+ p=li+1;
+ }
+ lab = stripProtectionPrefix(ei->label().right(ei->label().length()-p));
+ arrowNames.insert(lab,(void*)0x8);
+ }
+ }
+ }
+
+ //printf("DotNode::writeBox for %s\n",m_classDef->name().data());
+ t << "{" << convertLabel(m_label);
+ t << "\\n|";
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames);
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames);
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames);
+ writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames);
+ writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames);
+ writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames);
+ writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames);
+ if (Config_getBool(EXTRACT_PRIVATE))
+ {
+ writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames);
+ writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames);
+ }
+ t << "|";
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef);
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE);
+ writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef);
+ writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef);
+ writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE);
+ writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef);
+ writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE);
+ writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef);
+ if (Config_getBool(EXTRACT_PRIVATE))
+ {
+ writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef);
+ writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE);
+ writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef);
+ }
+ if (m_classDef->getLanguage()!=SrcLangExt_Fortran &&
+ m_classDef->getMemberGroupSDict())
+ {
+ MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict());
+ MemberGroup *mg;
+ for (mgdi.toFirst();(mg=mgdi.current());++mgdi)
+ {
+ if (mg->members())
+ {
+ writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames);
+ }
+ }
+ }
+ t << "}";
+ }
+ else // standard look
+ {
+ t << convertLabel(m_label);
+ }
+ t << "\",height=0.2,width=0.4";
+ if (m_isRoot)
+ {
+ t << ",color=\"black\", fillcolor=\"grey75\", style=\"filled\", fontcolor=\"black\"";
+ }
+ else
+ {
+ if (!Config_getBool(DOT_TRANSPARENT))
+ {
+ t << ",color=\"" << labCol << "\", fillcolor=\"";
+ t << "white";
+ t << "\", style=\"filled\"";
+ }
+ else
+ {
+ t << ",color=\"" << labCol << "\"";
+ }
+ if (!m_url.isEmpty())
+ {
+ int anchorPos = m_url.findRev('#');
+ if (anchorPos==-1)
+ {
+ t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\"";
+ }
+ else
+ {
+ t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension
+ << m_url.right(m_url.length()-anchorPos) << "\"";
+ }
+ }
+ }
+ if (!m_tooltip.isEmpty())
+ {
+ t << ",tooltip=\"" << escapeTooltip(m_tooltip) << "\"";
+ }
+ else
+ {
+ t << ",tooltip=\" \""; // space in tooltip is required otherwise still something like 'Node0' is used
+ }
+ t << "];" << endl;
+}
+
+void DotNode::writeArrow(FTextStream &t,
+ GraphType gt,
+ GraphOutputFormat format,
+ const DotNode *cn,
+ const EdgeInfo *ei,
+ bool topDown,
+ bool pointBack) const
+{
+ t << " Node";
+ if (topDown)
+ t << cn->number();
+ else
+ t << m_number;
+ t << " -> Node";
+ if (topDown)
+ t << m_number;
+ else
+ t << cn->number();
+ t << " [";
+
+ const EdgeProperties *eProps = Config_getBool(UML_LOOK) ? &umlEdgeProps : &normalEdgeProps;
+ QCString aStyle = eProps->arrowStyleMap[ei->color()];
+ bool umlUseArrow = aStyle=="odiamond";
+
+ if (pointBack && !umlUseArrow) t << "dir=\"back\",";
+ t << "color=\"" << eProps->edgeColorMap[ei->color()]
+ << "\",fontsize=\"" << DotGraph::DOT_FONTSIZE << "\",";
+ t << "style=\"" << eProps->edgeStyleMap[ei->style()] << "\"";
+ if (!ei->label().isEmpty())
+ {
+ t << ",label=\" " << convertLabel(ei->label()) << "\" ";
+ }
+ if (Config_getBool(UML_LOOK) &&
+ eProps->arrowStyleMap[ei->color()] &&
+ (gt==Inheritance || gt==Collaboration)
+ )
+ {
+ bool rev = pointBack;
+ if (umlUseArrow) rev=!rev; // UML use relates has arrow on the start side
+ if (rev)
+ t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->color()] << "\"";
+ else
+ t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\"";
+ }
+
+ if (format==GOF_BITMAP) t << ",fontname=\"" << DotGraph::DOT_FONTNAME << "\"";
+ t << "];" << endl;
+}
+
+void DotNode::write(FTextStream &t,
+ GraphType gt,
+ GraphOutputFormat format,
+ bool topDown,
+ bool toChildren,
+ bool backArrows) const
+{
+ //printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible);
+ if (m_written) return; // node already written to the output
+ if (!m_visible) return; // node is not visible
+ writeBox(t,gt,format,m_truncated==Truncated);
+ m_written=TRUE;
+ QList<DotNode> *nl = toChildren ? m_children : m_parents;
+ if (nl)
+ {
+ if (toChildren)
+ {
+ QListIterator<DotNode> dnli1(*nl);
+ QListIterator<EdgeInfo> dnli2(*m_edgeInfo);
+ const DotNode *cn;
+ for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
+ {
+ if (cn->isVisible())
+ {
+ //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",cn->label().data());
+ writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows);
+ }
+ cn->write(t,gt,format,topDown,toChildren,backArrows);
+ }
+ }
+ else // render parents
+ {
+ QListIterator<DotNode> dnli(*nl);
+ DotNode *pn;
+ for (dnli.toFirst();(pn=dnli.current());++dnli)
+ {
+ if (pn->isVisible())
+ {
+ //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",pn->label().data());
+ writeArrow(t,
+ gt,
+ format,
+ pn,
+ pn->edgeInfo()->at(pn->children()->findRef(this)),
+ FALSE,
+ backArrows
+ );
+ }
+ pn->write(t,gt,format,TRUE,FALSE,backArrows);
+ }
+ }
+ }
+ //printf("end DotNode::write(%d) name=%s\n",distance,m_label.data());
+}
+
+void DotNode::writeXML(FTextStream &t,bool isClassGraph) const
+{
+ t << " <node id=\"" << m_number << "\">" << endl;
+ t << " <label>" << convertToXML(m_label) << "</label>" << endl;
+ if (!m_url.isEmpty())
+ {
+ QCString url(m_url);
+ const char *refPtr = url.data();
+ char *urlPtr = strchr(url.rawData(),'$');
+ if (urlPtr)
+ {
+ *urlPtr++='\0';
+ t << " <link refid=\"" << convertToXML(urlPtr) << "\"";
+ if (*refPtr!='\0')
+ {
+ t << " external=\"" << convertToXML(refPtr) << "\"";
+ }
+ t << "/>" << endl;
+ }
+ }
+ if (m_children)
+ {
+ QListIterator<DotNode> nli(*m_children);
+ QListIterator<EdgeInfo> eli(*m_edgeInfo);
+ DotNode *childNode;
+ EdgeInfo *edgeInfo;
+ for (;(childNode=nli.current());++nli,++eli)
+ {
+ edgeInfo=eli.current();
+ t << " <childnode refid=\"" << childNode->number() << "\" relation=\"";
+ if (isClassGraph)
+ {
+ switch(edgeInfo->color())
+ {
+ case EdgeInfo::Blue: t << "public-inheritance"; break;
+ case EdgeInfo::Green: t << "protected-inheritance"; break;
+ case EdgeInfo::Red: t << "private-inheritance"; break;
+ case EdgeInfo::Purple: t << "usage"; break;
+ case EdgeInfo::Orange: t << "template-instance"; break;
+ case EdgeInfo::Orange2: t << "type-constraint"; break;
+ case EdgeInfo::Grey: ASSERT(0); break;
+ }
+ }
+ else // include graph
+ {
+ t << "include";
+ }
+ t << "\">" << endl;
+ if (!edgeInfo->label().isEmpty())
+ {
+ int p=0;
+ int ni;
+ while ((ni=edgeInfo->label().find('\n',p))!=-1)
+ {
+ t << " <edgelabel>"
+ << convertToXML(edgeInfo->label().mid(p,ni-p))
+ << "</edgelabel>" << endl;
+ p=ni+1;
+ }
+ t << " <edgelabel>"
+ << convertToXML(edgeInfo->label().right(edgeInfo->label().length()-p))
+ << "</edgelabel>" << endl;
+ }
+ t << " </childnode>" << endl;
+ }
+ }
+ t << " </node>" << endl;
+}
+
+void DotNode::writeDocbook(FTextStream &t,bool isClassGraph) const
+{
+ t << " <node id=\"" << m_number << "\">" << endl;
+ t << " <label>" << convertToXML(m_label) << "</label>" << endl;
+ if (!m_url.isEmpty())
+ {
+ QCString url(m_url);
+ const char *refPtr = url.data();
+ char *urlPtr = strchr(url.rawData(),'$');
+ if (urlPtr)
+ {
+ *urlPtr++='\0';
+ t << " <link refid=\"" << convertToXML(urlPtr) << "\"";
+ if (*refPtr!='\0')
+ {
+ t << " external=\"" << convertToXML(refPtr) << "\"";
+ }
+ t << "/>" << endl;
+ }
+ }
+ if (m_children)
+ {
+ QListIterator<DotNode> nli(*m_children);
+ QListIterator<EdgeInfo> eli(*m_edgeInfo);
+ DotNode *childNode;
+ EdgeInfo *edgeInfo;
+ for (;(childNode=nli.current());++nli,++eli)
+ {
+ edgeInfo=eli.current();
+ t << " <childnode refid=\"" << childNode->number() << "\" relation=\"";
+ if (isClassGraph)
+ {
+ switch(edgeInfo->color())
+ {
+ case EdgeInfo::Blue: t << "public-inheritance"; break;
+ case EdgeInfo::Green: t << "protected-inheritance"; break;
+ case EdgeInfo::Red: t << "private-inheritance"; break;
+ case EdgeInfo::Purple: t << "usage"; break;
+ case EdgeInfo::Orange: t << "template-instance"; break;
+ case EdgeInfo::Orange2: t << "type-constraint"; break;
+ case EdgeInfo::Grey: ASSERT(0); break;
+ }
+ }
+ else // include graph
+ {
+ t << "include";
+ }
+ t << "\">" << endl;
+ if (!edgeInfo->label().isEmpty())
+ {
+ int p=0;
+ int ni;
+ while ((ni=edgeInfo->label().find('\n',p))!=-1)
+ {
+ t << " <edgelabel>"
+ << convertToXML(edgeInfo->label().mid(p,ni-p))
+ << "</edgelabel>" << endl;
+ p=ni+1;
+ }
+ t << " <edgelabel>"
+ << convertToXML(edgeInfo->label().right(edgeInfo->label().length()-p))
+ << "</edgelabel>" << endl;
+ }
+ t << " </childnode>" << endl;
+ }
+ }
+ t << " </node>" << endl;
+}
+
+
+void DotNode::writeDEF(FTextStream &t) const
+{
+ const char* nodePrefix = " node-";
+
+ t << " node = {" << endl;
+ t << nodePrefix << "id = " << m_number << ';' << endl;
+ t << nodePrefix << "label = '" << m_label << "';" << endl;
+
+ if (!m_url.isEmpty())
+ {
+ QCString url(m_url);
+ const char *refPtr = url.data();
+ char *urlPtr = strchr(url.rawData(),'$');
+ if (urlPtr)
+ {
+ *urlPtr++='\0';
+ t << nodePrefix << "link = {" << endl << " "
+ << nodePrefix << "link-id = '" << urlPtr << "';" << endl;
+
+ if (*refPtr!='\0')
+ {
+ t << " " << nodePrefix << "link-external = '"
+ << refPtr << "';" << endl;
+ }
+ t << " };" << endl;
+ }
+ }
+ if (m_children)
+ {
+ QListIterator<DotNode> nli(*m_children);
+ QListIterator<EdgeInfo> eli(*m_edgeInfo);
+ DotNode *childNode;
+ EdgeInfo *edgeInfo;
+ for (;(childNode=nli.current());++nli,++eli)
+ {
+ edgeInfo=eli.current();
+ t << " node-child = {" << endl;
+ t << " child-id = '" << childNode->number() << "';" << endl;
+ t << " relation = ";
+
+ switch(edgeInfo->color())
+ {
+ case EdgeInfo::Blue: t << "public-inheritance"; break;
+ case EdgeInfo::Green: t << "protected-inheritance"; break;
+ case EdgeInfo::Red: t << "private-inheritance"; break;
+ case EdgeInfo::Purple: t << "usage"; break;
+ case EdgeInfo::Orange: t << "template-instance"; break;
+ case EdgeInfo::Orange2: t << "type-constraint"; break;
+ case EdgeInfo::Grey: ASSERT(0); break;
+ }
+ t << ';' << endl;
+
+ if (!edgeInfo->label().isEmpty())
+ {
+ t << " edgelabel = <<_EnD_oF_dEf_TeXt_" << endl
+ << edgeInfo->label() << endl
+ << "_EnD_oF_dEf_TeXt_;" << endl;
+ }
+ t << " }; /* node-child */" << endl;
+ } /* for (;childNode...) */
+ }
+ t << " }; /* node */" << endl;
+}
+
+
+void DotNode::clearWriteFlag()
+{
+ m_written=FALSE;
+ if (m_parents!=0)
+ {
+ QListIterator<DotNode> dnlip(*m_parents);
+ DotNode *pn;
+ for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
+ {
+ if (pn->isWritten())
+ {
+ pn->clearWriteFlag();
+ }
+ }
+ }
+ if (m_children!=0)
+ {
+ QListIterator<DotNode> dnlic(*m_children);
+ DotNode *cn;
+ for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
+ {
+ if (cn->isWritten())
+ {
+ cn->clearWriteFlag();
+ }
+ }
+ }
+}
+
+void DotNode::colorConnectedNodes(int curColor)
+{
+ if (m_children)
+ {
+ QListIterator<DotNode> dnlic(*m_children);
+ DotNode *cn;
+ for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
+ {
+ if (cn->subgraphId()==-1) // uncolored child node
+ {
+ cn->setSubgraphId(curColor);
+ cn->markAsVisible();
+ cn->colorConnectedNodes(curColor);
+ //printf("coloring node %s (%p): %d\n",cn->label().data(),cn,cn->subgraphId());
+ }
+ }
+ }
+
+ if (m_parents)
+ {
+ QListIterator<DotNode> dnlip(*m_parents);
+ DotNode *pn;
+ for (dnlip.toFirst();(pn=dnlip.current());++dnlip)
+ {
+ if (pn->subgraphId()==-1) // uncolored parent node
+ {
+ pn->setSubgraphId(curColor);
+ pn->markAsVisible();
+ pn->colorConnectedNodes(curColor);
+ //printf("coloring node %s (%p): %d\n",pn->label().data(),pn,pn->subgraphId());
+ }
+ }
+ }
+}
+
+void DotNode::renumberNodes(int &number)
+{
+ m_number = number++;
+ if (m_children)
+ {
+ QListIterator<DotNode> dnlic(*m_children);
+ DotNode *cn;
+ for (dnlic.toFirst();(cn=dnlic.current());++dnlic)
+ {
+ if (!cn->isRenumbered())
+ {
+ cn->markRenumbered();
+ cn->renumberNodes(number);
+ }
+ }
+ }
+}
+
+const DotNode *DotNode::findDocNode() const
+{
+ if (!m_url.isEmpty()) return this;
+ //printf("findDocNode(): `%s'\n",m_label.data());
+ if (m_parents)
+ {
+ QListIterator<DotNode> dnli(*m_parents);
+ DotNode *pn;
+ for (dnli.toFirst();(pn=dnli.current());++dnli)
+ {
+ if (!pn->hasDocumentation())
+ {
+ pn->markHasDocumentation();
+ const DotNode *dn = pn->findDocNode();
+ if (dn) return dn;
+ }
+ }
+ }
+ if (m_children)
+ {
+ QListIterator<DotNode> dnli(*m_children);
+ DotNode *cn;
+ for (dnli.toFirst();(cn=dnli.current());++dnli)
+ {
+ if (!cn->hasDocumentation())
+ {
+ cn->markHasDocumentation();
+ const DotNode *dn = cn->findDocNode();
+ if (dn) return dn;
+ }
+ }
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------
+
+int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const
+{
+ return qstricmp(n1->label(),n2->label());
+}
+
+
+
diff --git a/src/dotnode.h b/src/dotnode.h
new file mode 100644
index 0000000..334fdef
--- /dev/null
+++ b/src/dotnode.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTNODE_H
+#define DOTNODE_H
+
+#include "sortdict.h"
+
+#include "dotgraph.h"
+
+class ClassDef;
+class DotNodeList;
+class FTextStream;
+
+/** Attributes of an edge of a dot graph */
+class EdgeInfo
+{
+ public:
+ enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5, Orange2=6 };
+ enum Styles { Solid=0, Dashed=1 };
+ EdgeInfo(int color,int style,const QCString &lab,const QCString &url,int labColor)
+ : m_color(color), m_style(style), m_label(lab), m_url(url), m_labColor(labColor) {}
+ ~EdgeInfo() {}
+ int color() const { return m_color; }
+ int style() const { return m_style; }
+ QCString label() const { return m_label; }
+ QCString url() const { return m_url; }
+ int labelColor() const { return m_labColor; }
+ private:
+ int m_color;
+ int m_style;
+ QCString m_label;
+ QCString m_url;
+ int m_labColor;
+};
+
+/** A node in a dot graph */
+class DotNode
+{
+ public:
+ static void deleteNodes(DotNode* node, SDict<DotNode>* skipNodes = 0);
+ static QCString convertLabel(const QCString& l);
+ DotNode(int n,const char *lab,const char *tip,const char *url,
+ bool rootNode=FALSE,const ClassDef *cd=0);
+ ~DotNode();
+
+ enum TruncState { Unknown, Truncated, Untruncated };
+
+ void addChild(DotNode *n,
+ int edgeColor=EdgeInfo::Purple,
+ int edgeStyle=EdgeInfo::Solid,
+ const char *edgeLab=0,
+ const char *edgeURL=0,
+ int edgeLabCol=-1);
+ void addParent(DotNode *n);
+ void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0);
+ void removeChild(DotNode *n);
+ void removeParent(DotNode *n);
+ int findParent( DotNode *n );
+
+ void write(FTextStream &t,GraphType gt,GraphOutputFormat f,
+ bool topDown,bool toChildren,bool backArrows) const;
+ void writeXML(FTextStream &t,bool isClassGraph) const;
+ void writeDocbook(FTextStream &t,bool isClassGraph) const;
+ void writeDEF(FTextStream &t) const;
+ void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f,
+ bool hasNonReachableChildren) const;
+ void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,const DotNode *cn,
+ const EdgeInfo *ei,bool topDown, bool pointBack=TRUE) const;
+
+ QCString label() const { return m_label; }
+ int number() const { return m_number; }
+ bool isVisible() const { return m_visible; }
+ TruncState isTruncated() const { return m_truncated; }
+ int distance() const { return m_distance; }
+ int subgraphId() const { return m_subgraphId; }
+ bool isRenumbered() const { return m_renumbered; }
+ bool hasDocumentation() const { return m_hasDoc; }
+ bool isWritten() const { return m_written; }
+
+ void clearWriteFlag();
+ void renumberNodes(int &number);
+ void markRenumbered() { m_renumbered = true; }
+ void markHasDocumentation() { m_hasDoc = true; }
+ void setSubgraphId(int id) { m_subgraphId = id; }
+
+ void colorConnectedNodes(int curColor);
+ void setDistance(int distance);
+ const DotNode *findDocNode() const; // only works for acyclic graphs!
+ void markAsVisible(bool b=TRUE) { m_visible=b; }
+ void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; }
+ const QList<DotNode> *children() const { return m_children; }
+ const QList<DotNode> *parents() const { return m_parents; }
+ const QList<EdgeInfo> *edgeInfo() const { return m_edgeInfo; }
+
+ private:
+ int m_number;
+ QCString m_label; //!< label text
+ QCString m_tooltip; //!< node's tooltip
+ QCString m_url; //!< url of the node (format: remote$local)
+ QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows)
+ QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows)
+ QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child
+ bool m_deleted; //!< used to mark a node as deleted
+ mutable bool m_written; //!< used to mark a node as written
+ bool m_hasDoc; //!< used to mark a node as documented
+ bool m_isRoot; //!< indicates if this is a root node
+ const ClassDef * m_classDef; //!< class representing this node (can be 0)
+ bool m_visible; //!< is the node visible in the output
+ TruncState m_truncated; //!< does the node have non-visible children/parents
+ int m_distance; //!< shortest path to the root node
+ bool m_renumbered;//!< indicates if the node has been renumbered (to prevent endless loops)
+ int m_subgraphId;
+};
+
+/** Class representing a list of DotNode objects. */
+class DotNodeList : public QList<DotNode>
+{
+ public:
+ DotNodeList() : QList<DotNode>() {}
+ ~DotNodeList() {}
+ private:
+ int compareValues(const DotNode *n1,const DotNode *n2) const;
+};
+
+#endif
diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp
new file mode 100644
index 0000000..22a0081
--- /dev/null
+++ b/src/dotrunner.cpp
@@ -0,0 +1,294 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#include "dotrunner.h"
+
+#include "util.h"
+#include "portable.h"
+#include "dot.h"
+#include "message.h"
+#include "ftextstream.h"
+#include "config.h"
+
+// the graphicx LaTeX has a limitation of maximum size of 16384
+// To be on the save side we take it a little bit smaller i.e. 150 inch * 72 dpi
+// It is anyway hard to view these size of images
+#define MAX_LATEX_GRAPH_INCH 150
+#define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72)
+
+
+// since dot silently reproduces the input file when it does not
+// support the PNG format, we need to check the result.
+static void checkPngResult(const char *imgName)
+{
+ FILE *f = portable_fopen(imgName,"rb");
+ if (f)
+ {
+ char data[4];
+ if (fread(data,1,4,f)==4)
+ {
+ if (!(data[1]=='P' && data[2]=='N' && data[3]=='G'))
+ {
+ err("Image `%s' produced by dot is not a valid PNG!\n"
+ "You should either select a different format "
+ "(DOT_IMAGE_FORMAT in the config file) or install a more "
+ "recent version of graphviz (1.7+)\n",imgName
+ );
+ }
+ }
+ else
+ {
+ err("Could not read image `%s' generated by dot!\n",imgName);
+ }
+ fclose(f);
+ }
+ else
+ {
+ err("Could not open image `%s' generated by dot!\n",imgName);
+ }
+}
+
+static bool resetPDFSize(const int width,const int height, const char *base)
+{
+ QString tmpName = QString::fromUtf8(QCString(base)+".tmp");
+ QString patchFile = QString::fromUtf8(QCString(base)+".dot");
+ if (!QDir::current().rename(patchFile,tmpName))
+ {
+ err("Failed to rename file %s to %s!\n",patchFile.data(),tmpName.data());
+ return FALSE;
+ }
+ QFile fi(tmpName);
+ QFile fo(patchFile);
+ if (!fi.open(IO_ReadOnly))
+ {
+ err("problem opening file %s for patching!\n",tmpName.data());
+ QDir::current().rename(tmpName,patchFile);
+ return FALSE;
+ }
+ if (!fo.open(IO_WriteOnly))
+ {
+ err("problem opening file %s for patching!\n",patchFile.data());
+ QDir::current().rename(tmpName,patchFile);
+ fi.close();
+ return FALSE;
+ }
+ FTextStream t(&fo);
+ const int maxLineLen=100*1024;
+ while (!fi.atEnd()) // foreach line
+ {
+ QCString line(maxLineLen);
+ int numBytes = fi.readLine(line.rawData(),maxLineLen);
+ if (numBytes<=0)
+ {
+ break;
+ }
+ line.resize(numBytes+1);
+ if (line.find("LATEX_PDF_SIZE") != -1)
+ {
+ double scale = (width > height ? width : height)/double(MAX_LATEX_GRAPH_INCH);
+ t << " size=\""<<width/scale << "," <<height/scale <<"\";\n";
+ }
+ else
+ t << line;
+ }
+ fi.close();
+ fo.close();
+ // remove temporary file
+ QDir::current().remove(tmpName);
+ return TRUE;
+}
+
+bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool isEps)
+{
+ const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox [";
+ int bblen = strlen(bb);
+ FILE *f = portable_fopen(fileName,"rb");
+ if (!f)
+ {
+ //printf("readBoundingBox: could not open %s\n",fileName);
+ return FALSE;
+ }
+ const int maxLineLen=1024;
+ char buf[maxLineLen];
+ while (fgets(buf,maxLineLen,f)!=NULL)
+ {
+ const char *p = strstr(buf,bb);
+ if (p) // found PageBoundingBox or /MediaBox string
+ {
+ int x,y;
+ fclose(f);
+ if (sscanf(p+bblen,"%d %d %d %d",&x,&y,width,height)!=4)
+ {
+ //printf("readBoundingBox sscanf fail\n");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ err("Failed to extract bounding box from generated diagram file %s\n",fileName);
+ fclose(f);
+ return FALSE;
+}
+
+bool DotRunner::DOT_CLEANUP;
+bool DotRunner::DOT_MULTI_TARGETS;
+DotConstString DotRunner::DOT_EXE;
+
+DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash)
+ : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(DOT_CLEANUP)
+{
+ m_jobs.setAutoDelete(TRUE);
+}
+
+void DotRunner::addJob(const char *format,const char *output)
+{
+ QListIterator<DotJob> li(m_jobs);
+ DotJob *s;
+ for (li.toFirst(); (s = li.current()); ++li)
+ {
+ if (qstrcmp(s->format.data(), format) != 0) continue;
+ if (qstrcmp(s->output.data(), output) != 0) continue;
+ // we have this job already
+ return;
+ }
+ QCString args = QCString("-T")+format+" -o \""+output+"\"";
+ m_jobs.append(new DotJob(format, output, args));
+}
+
+QCString getBaseNameOfOutput(QCString const& output)
+{
+ int index = output.findRev('.');
+ if (index < 0) return output;
+ return output.left(index);
+}
+
+bool DotRunner::run()
+{
+ int exitCode=0;
+
+ QCString dotArgs;
+ QListIterator<DotJob> li(m_jobs);
+ DotJob *s;
+
+ // create output
+ if (DOT_MULTI_TARGETS)
+ {
+ dotArgs=QCString("\"")+m_file.data()+"\"";
+ for (li.toFirst();(s=li.current());++li)
+ {
+ dotArgs+=' ';
+ dotArgs+=s->args.data();
+ }
+ if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error;
+ }
+ else
+ {
+ for (li.toFirst();(s=li.current());++li)
+ {
+ dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data();
+ if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error;
+ }
+ }
+
+ // check output
+ // As there should be only one pdf file be generated, we don't need code for regenerating multiple pdf files in one call
+ for (li.toFirst();(s=li.current());++li)
+ {
+ if (qstrncmp(s->format.data(), "pdf", 3) == 0)
+ {
+ int width=0,height=0;
+ if (!readBoundingBox(s->output.data(),&width,&height,FALSE)) goto error;
+ if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE))
+ {
+ if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error;
+ dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data();
+ if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error;
+ }
+ }
+
+ if (qstrncmp(s->format.data(), "png", 3) == 0)
+ {
+ checkPngResult(s->output.data());
+ }
+ }
+
+ // remove .dot files
+ if (m_cleanUp)
+ {
+ //printf("removing dot file %s\n",m_file.data());
+ portable_unlink(m_file.data());
+ }
+
+ // create checksum file
+ if (!m_md5Hash.isEmpty())
+ {
+ QCString md5Name = getBaseNameOfOutput(m_file.data()) + ".md5";
+ FILE *f = portable_fopen(md5Name,"w");
+ if (f)
+ {
+ fwrite(m_md5Hash.data(),1,32,f);
+ fclose(f);
+ }
+ }
+ return TRUE;
+error:
+ err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n",
+ exitCode,DOT_EXE.data(),dotArgs.data());
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------
+
+void DotRunnerQueue::enqueue(DotRunner *runner)
+{
+ QMutexLocker locker(&m_mutex);
+ m_queue.enqueue(runner);
+ m_bufferNotEmpty.wakeAll();
+}
+
+DotRunner *DotRunnerQueue::dequeue()
+{
+ QMutexLocker locker(&m_mutex);
+ while (m_queue.isEmpty())
+ {
+ // wait until something is added to the queue
+ m_bufferNotEmpty.wait(&m_mutex);
+ }
+ DotRunner *result = m_queue.dequeue();
+ return result;
+}
+
+uint DotRunnerQueue::count() const
+{
+ QMutexLocker locker(&m_mutex);
+ return m_queue.count();
+}
+
+//--------------------------------------------------------------------
+
+DotWorkerThread::DotWorkerThread(DotRunnerQueue *queue)
+ : m_queue(queue)
+{
+}
+
+void DotWorkerThread::run()
+{
+ DotRunner *runner;
+ while ((runner=m_queue->dequeue()))
+ {
+ runner->run();
+ }
+}
diff --git a/src/dotrunner.h b/src/dotrunner.h
new file mode 100644
index 0000000..4128fe8
--- /dev/null
+++ b/src/dotrunner.h
@@ -0,0 +1,138 @@
+/******************************************************************************
+*
+* Copyright (C) 1997-2019 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.
+*
+* Documents produced by Doxygen are derivative works derived from the
+* input used in their production; they are not affected by this license.
+*
+*/
+
+#ifndef DOTRUNNER_H
+#define DOTRUNNER_H
+
+#include "qcstring.h"
+#include "qlist.h"
+#include "qwaitcondition.h"
+#include "qthread.h"
+#include "qqueue.h"
+#include "qmutex.h"
+
+/** Minimal constant string class that is thread safe, once initialized. */
+class DotConstString
+{
+ public:
+ DotConstString() { m_str=0;}
+ ~DotConstString() { delete[] m_str;}
+ DotConstString(char const* s) : m_str(0) { set(s); }
+ DotConstString(const QCString &s) : m_str(0) { set(s); }
+ DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); }
+ const char *data() const { return m_str; }
+ bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; }
+ void init(const char *s) { set(s); }
+
+ private:
+ void set(char const* s)
+ {
+ delete[] m_str;
+ m_str=0;
+ if (s)
+ {
+ m_str=new char[strlen(s) + 1];
+ qstrcpy(m_str,s);
+ }
+ }
+
+ void set(const QCString &s)
+ {
+ delete[] m_str;
+ m_str=0;
+ if (!s.isEmpty())
+ {
+ m_str=new char[s.length()+1];
+ qstrcpy(m_str,s.data());
+ }
+ }
+
+ DotConstString &operator=(const DotConstString &);
+
+ char *m_str;
+};
+
+/** Helper class to run dot from doxygen from multiple threads. */
+class DotRunner
+{
+ public:
+ struct DotJob
+ {
+ DotJob(const DotConstString & format,
+ const DotConstString & output,
+ const DotConstString & args)
+ : format(format), output(output), args(args) {}
+ DotConstString format;
+ DotConstString output;
+ DotConstString args;
+ };
+
+ /** Creates a runner for a dot \a file. */
+ DotRunner(const QCString& absDotName, const QCString& md5Hash);
+
+ /** Adds an additional job to the run.
+ * Performing multiple jobs one file can be faster.
+ */
+ void addJob(const char *format,const char *output);
+
+ /** Prevent cleanup of the dot file (for user provided dot files) */
+ void preventCleanUp() { m_cleanUp = FALSE; }
+
+ /** Runs dot for all jobs added. */
+ bool run();
+
+ // DotConstString const& getFileName() { return m_file; }
+ DotConstString const& getMd5Hash() { return m_md5Hash; }
+
+ static bool readBoundingBox(const char* fileName, int* width, int* height, bool isEps);
+
+ private:
+ DotConstString m_file;
+ DotConstString m_md5Hash;
+ bool m_cleanUp;
+ QList<DotJob> m_jobs;
+
+ static bool DOT_CLEANUP;
+ static bool DOT_MULTI_TARGETS;
+ static DotConstString DOT_EXE;
+ friend void initDot();
+
+};
+
+/** Queue of dot jobs to run. */
+// all methods are thread save
+class DotRunnerQueue
+{
+ public:
+ void enqueue(DotRunner *runner);
+ DotRunner *dequeue();
+ uint count() const;
+ private:
+ QWaitCondition m_bufferNotEmpty;
+ QQueue<DotRunner> m_queue;
+ mutable QMutex m_mutex;
+};
+
+/** Worker thread to execute a dot run */
+class DotWorkerThread : public QThread
+{
+ public:
+ DotWorkerThread(DotRunnerQueue *queue);
+ void run();
+ private:
+ DotRunnerQueue *m_queue;
+};
+
+#endif
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 9c98d8c..92e5292 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -174,6 +174,7 @@ QCString Doxygen::spaces;
bool Doxygen::generatingXmlOutput = FALSE;
bool Doxygen::markdownSupport = TRUE;
GenericsSDict *Doxygen::genericsDict;
+DocGroup Doxygen::docGroup;
// locally accessible globals
static QDict<Entry> g_classEntries(1009);
@@ -766,6 +767,16 @@ static void buildFileList(Entry *root)
{
bool ambig;
FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig);
+ if (!fd || ambig)
+ {
+ int save_ambig = ambig;
+ // use the directory of the file to see if the described file is in the same
+ // directory as the describing file.
+ QCString fn = root->fileName;
+ int newIndex=fn.findRev('/');
+ fd=findFileDef(Doxygen::inputNameDict,fn.left(newIndex) + "/" + root->name,ambig);
+ if (!fd) ambig = save_ambig;
+ }
//printf("**************** root->name=%s fd=%p\n",root->name.data(),fd);
if (fd && !ambig)
{
@@ -795,7 +806,7 @@ static void buildFileList(Entry *root)
const char *fn = root->fileName.data();
QCString text(4096);
text.sprintf("the name `%s' supplied as "
- "the second argument in the \\file statement ",
+ "the argument in the \\file statement ",
qPrint(root->name));
if (ambig) // name is ambiguous
{
@@ -1209,7 +1220,6 @@ ClassDef::CompoundType convertToCompoundType(int section,uint64 specifier)
static void addClassToContext(Entry *root)
{
- //printf("Loading entry for rootNav=%p name=%s\n",rootNav,rootNav->name().data());
FileDef *fd = root->fileDef();
QCString scName;
@@ -1423,6 +1433,31 @@ static void resolveClassNestingRelations()
//printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration);
d->addInnerCompound(cd);
cd->setOuterScope(d);
+
+ // for inline namespace add an alias of the class to the outer scope
+ while (d->definitionType()==DefinitionIntf::TypeNamespace)
+ {
+ NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d);
+ //printf("d->isInline()=%d\n",nd->isInline());
+ if (nd->isInline())
+ {
+ d = d->getOuterScope();
+ if (d)
+ {
+ ClassDef *aliasCd = createClassDefAlias(d,cd);
+ d->addInnerCompound(aliasCd);
+ QCString aliasFullName = d->qualifiedName()+"::"+aliasCd->localName();
+ Doxygen::classSDict->append(aliasFullName,aliasCd);
+ printf("adding %s to %s as %s\n",qPrint(aliasCd->name()),qPrint(d->name()),qPrint(aliasFullName));
+ aliasCd->setVisited(TRUE);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
cd->setVisited(TRUE);
done=FALSE;
}
@@ -1752,6 +1787,7 @@ static void buildNamespaceList(Entry *root)
nd->setLanguage(root->lang);
nd->setId(root->id);
nd->setMetaData(root->metaData);
+ nd->setInline((root->spec&Entry::Inline)!=0);
//printf("Adding namespace to group\n");
addNamespaceToGroups(root,nd);
@@ -1786,6 +1822,25 @@ static void buildNamespaceList(Entry *root)
{
d->addInnerCompound(nd);
nd->setOuterScope(d);
+ // in case of d is an inline namespace, alias insert nd in the part scope of d.
+ while (d->definitionType()==DefinitionIntf::TypeNamespace)
+ {
+ NamespaceDef *pnd = dynamic_cast<NamespaceDef*>(d);
+ if (pnd->isInline())
+ {
+ d = d->getOuterScope();
+ if (d)
+ {
+ NamespaceDef *aliasNd = createNamespaceDefAlias(d,nd);
+ //printf("adding %s to %s\n",qPrint(aliasNd->name()),qPrint(d->name()));
+ d->addInnerCompound(aliasNd);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
}
}
}
@@ -1795,15 +1850,15 @@ static void buildNamespaceList(Entry *root)
//----------------------------------------------------------------------
-static NamespaceDef *findUsedNamespace(NamespaceSDict *unl,
+static const NamespaceDef *findUsedNamespace(const NamespaceSDict *unl,
const QCString &name)
{
- NamespaceDef *usingNd =0;
+ const NamespaceDef *usingNd =0;
if (unl)
{
//printf("Found namespace dict %d\n",unl->count());
NamespaceSDict::Iterator unli(*unl);
- NamespaceDef *und;
+ const NamespaceDef *und;
for (unli.toFirst();(und=unli.current());++unli)
{
QCString uScope=und->name()+"::";
@@ -1827,7 +1882,7 @@ static void findUsingDirectives(Entry *root)
}
if (!name.isEmpty())
{
- NamespaceDef *usingNd = 0;
+ const NamespaceDef *usingNd = 0;
NamespaceDef *nd = 0;
FileDef *fd = root->fileDef();
QCString nsName;
@@ -1869,17 +1924,17 @@ static void findUsingDirectives(Entry *root)
if (usingNd==0 && nd) // not found, try used namespaces in this scope
// or in one of the parent namespace scopes
{
- NamespaceDef *pnd = nd;
+ const NamespaceDef *pnd = nd;
while (pnd && usingNd==0)
{
// also try with one of the used namespaces found earlier
usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name);
// goto the parent
- Definition *s = pnd->getOuterScope();
+ const Definition *s = pnd->getOuterScope();
if (s && s->definitionType()==Definition::TypeNamespace)
{
- pnd = dynamic_cast<NamespaceDef*>(s);
+ pnd = dynamic_cast<const NamespaceDef*>(s);
}
else
{
@@ -1923,6 +1978,7 @@ static void findUsingDirectives(Entry *root)
nd->setLanguage(root->lang);
nd->setId(root->id);
nd->setMetaData(root->metaData);
+ nd->setInline((root->spec&Entry::Inline)!=0);
QListIterator<Grouping> gli(*root->groups);
Grouping *g;
@@ -2014,7 +2070,7 @@ static void findUsingDeclarations(Entry *root)
// vector -> std::vector
if (usingCd==0)
{
- usingCd = getResolvedClass(nd,fd,name); // try via resolving (see also bug757509)
+ usingCd = const_cast<ClassDef*>(getResolvedClass(nd,fd,name)); // try via resolving (see also bug757509)
}
if (usingCd==0)
{
@@ -2080,7 +2136,7 @@ static void findUsingDeclImports(Entry *root)
{
QCString scope=root->name.left(i);
QCString memName=root->name.right(root->name.length()-i-2);
- ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter
+ const ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter
if (bcd)
{
//printf("found class %s memName=%s\n",bcd->name().data(),memName.data());
@@ -2105,8 +2161,8 @@ static void findUsingDeclImports(Entry *root)
{
fileName = root->tagInfo->tagName;
}
- ArgumentList *templAl = md->templateArguments();
- ArgumentList *al = md->templateArguments();
+ const ArgumentList *templAl = md->templateArguments();
+ const ArgumentList *al = md->templateArguments();
newMd = createMemberDef(
fileName,root->startLine,root->startColumn,
md->typeString(),memName,md->argsString(),
@@ -2272,7 +2328,8 @@ static MemberDef *addVariableToClass(
{
//printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n",
// md->getClassDef(),cd,root->type.data(),md->typeString());
- if (md->getClassDef()==cd &&
+ if (!md->isAlias() &&
+ md->getClassDef()==cd &&
removeRedundantWhiteSpace(root->type)==md->typeString())
// member already in the scope
{
@@ -2500,7 +2557,7 @@ static MemberDef *addVariableToFile(
MemberDef *md;
for (mni.toFirst();(md=mni.current());++mni)
{
- if (
+ if (!md->isAlias() &&
((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() &&
root->fileName==md->getFileDef()->absFilePath()
) // both variable names in the same file
@@ -3541,146 +3598,149 @@ static void buildFunctionList(Entry *root)
MemberNameIterator mni(*mn);
for (mni.toFirst();(!found && (md=mni.current()));++mni)
{
- NamespaceDef *mnd = md->getNamespaceDef();
- NamespaceDef *rnd = 0;
- //printf("root namespace=%s\n",rootNav->parent()->name().data());
- QCString fullScope = scope;
- QCString parentScope = root->parent()->name;
- if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
+ if (!md->isAlias())
{
- if (!scope.isEmpty()) fullScope.prepend("::");
- fullScope.prepend(parentScope);
- }
- //printf("fullScope=%s\n",fullScope.data());
- rnd = getResolvedNamespace(fullScope);
- FileDef *mfd = md->getFileDef();
- QCString nsName,rnsName;
- if (mnd) nsName = mnd->name().copy();
- if (rnd) rnsName = rnd->name().copy();
- //printf("matching arguments for %s%s %s%s\n",
- // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data());
- ArgumentList *mdAl = md->argumentList();
- ArgumentList *mdTempl = md->templateArguments();
-
- // in case of template functions, we need to check if the
- // functions have the same number of template parameters
- bool sameNumTemplateArgs = TRUE;
- bool matchingReturnTypes = TRUE;
- if (mdTempl!=0 && root->tArgLists)
- {
- if (mdTempl->count()!=root->tArgLists->getLast()->count())
+ const NamespaceDef *mnd = md->getNamespaceDef();
+ NamespaceDef *rnd = 0;
+ //printf("root namespace=%s\n",rootNav->parent()->name().data());
+ QCString fullScope = scope;
+ QCString parentScope = root->parent()->name;
+ if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
{
- sameNumTemplateArgs = FALSE;
+ if (!scope.isEmpty()) fullScope.prepend("::");
+ fullScope.prepend(parentScope);
}
- if (md->typeString()!=removeRedundantWhiteSpace(root->type))
+ //printf("fullScope=%s\n",fullScope.data());
+ rnd = getResolvedNamespace(fullScope);
+ const FileDef *mfd = md->getFileDef();
+ QCString nsName,rnsName;
+ if (mnd) nsName = mnd->name().copy();
+ if (rnd) rnsName = rnd->name().copy();
+ //printf("matching arguments for %s%s %s%s\n",
+ // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data());
+ ArgumentList *mdAl = md->argumentList();
+ const ArgumentList *mdTempl = md->templateArguments();
+
+ // in case of template functions, we need to check if the
+ // functions have the same number of template parameters
+ bool sameNumTemplateArgs = TRUE;
+ bool matchingReturnTypes = TRUE;
+ if (mdTempl!=0 && root->tArgLists)
{
- matchingReturnTypes = FALSE;
+ if (mdTempl->count()!=root->tArgLists->getLast()->count())
+ {
+ sameNumTemplateArgs = FALSE;
+ }
+ if (md->typeString()!=removeRedundantWhiteSpace(root->type))
+ {
+ matchingReturnTypes = FALSE;
+ }
}
- }
- bool staticsInDifferentFiles =
- root->stat && md->isStatic() && root->fileName!=md->getDefFileName();
+ bool staticsInDifferentFiles =
+ root->stat && md->isStatic() && root->fileName!=md->getDefFileName();
- if (
- matchArguments2(md->getOuterScope(),mfd,mdAl,
- rnd ? rnd : Doxygen::globalScope,rfd,root->argList,
- FALSE) &&
- sameNumTemplateArgs &&
- matchingReturnTypes &&
- !staticsInDifferentFiles
- )
- {
- GroupDef *gd=0;
- if (root->groups->getFirst()!=0)
- {
- gd = Doxygen::groupSDict->find(root->groups->getFirst()->groupname.data());
- }
- //printf("match!\n");
- //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
- // see if we need to create a new member
- found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
- ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
- mfd->absFilePath()==root->fileName // prototype in the same file
- )
- );
- // otherwise, allow a duplicate global member with the same argument list
- if (!found && gd && gd==md->getGroupDef() && nsName==rnsName)
+ if (
+ matchArguments2(md->getOuterScope(),mfd,mdAl,
+ rnd ? rnd : Doxygen::globalScope,rfd,root->argList,
+ FALSE) &&
+ sameNumTemplateArgs &&
+ matchingReturnTypes &&
+ !staticsInDifferentFiles
+ )
{
- // member is already in the group, so we don't want to add it again.
- found=TRUE;
- }
+ GroupDef *gd=0;
+ if (root->groups->getFirst()!=0)
+ {
+ gd = Doxygen::groupSDict->find(root->groups->getFirst()->groupname.data());
+ }
+ //printf("match!\n");
+ //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
+ // see if we need to create a new member
+ found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
+ ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
+ mfd->absFilePath()==root->fileName // prototype in the same file
+ )
+ );
+ // otherwise, allow a duplicate global member with the same argument list
+ if (!found && gd && gd==md->getGroupDef() && nsName==rnsName)
+ {
+ // member is already in the group, so we don't want to add it again.
+ found=TRUE;
+ }
- //printf("combining function with prototype found=%d in namespace %s\n",
- // found,nsName.data());
+ //printf("combining function with prototype found=%d in namespace %s\n",
+ // found,nsName.data());
- if (found)
- {
- // merge argument lists
- mergeArguments(mdAl,root->argList,!root->doc.isEmpty());
- // merge documentation
- if (md->documentation().isEmpty() && !root->doc.isEmpty())
+ if (found)
{
- ArgumentList *argList = new ArgumentList;
- stringToArgumentList(root->args,argList);
- if (root->proto)
+ // merge argument lists
+ mergeArguments(mdAl,root->argList,!root->doc.isEmpty());
+ // merge documentation
+ if (md->documentation().isEmpty() && !root->doc.isEmpty())
{
- //printf("setDeclArgumentList to %p\n",argList);
- md->setDeclArgumentList(argList);
+ ArgumentList *argList = new ArgumentList;
+ stringToArgumentList(root->args,argList);
+ if (root->proto)
+ {
+ //printf("setDeclArgumentList to %p\n",argList);
+ md->setDeclArgumentList(argList);
+ }
+ else
+ {
+ md->setArgumentList(argList);
+ }
}
- else
+
+ md->setDocumentation(root->doc,root->docFile,root->docLine);
+ md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
+ md->setDocsForDefinition(!root->proto);
+ if (md->getStartBodyLine()==-1 && root->bodyLine!=-1)
{
- md->setArgumentList(argList);
+ md->setBodySegment(root->bodyLine,root->endBodyLine);
+ md->setBodyDef(rfd);
}
- }
-
- md->setDocumentation(root->doc,root->docFile,root->docLine);
- md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
- md->setDocsForDefinition(!root->proto);
- if (md->getStartBodyLine()==-1 && root->bodyLine!=-1)
- {
- md->setBodySegment(root->bodyLine,root->endBodyLine);
- md->setBodyDef(rfd);
- }
- if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
- {
- md->setArgsString(root->args);
- }
- md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
+ if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
+ {
+ md->setArgsString(root->args);
+ }
+ md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
- md->addSectionsToDefinition(root->anchors);
+ md->addSectionsToDefinition(root->anchors);
- md->enableCallGraph(md->hasCallGraph() || root->callGraph);
- md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
- md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation);
- md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation);
+ md->enableCallGraph(md->hasCallGraph() || root->callGraph);
+ md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
+ md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation);
+ md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation);
- // merge ingroup specifiers
- if (md->getGroupDef()==0 && root->groups->getFirst()!=0)
- {
- addMemberToGroups(root,md);
- }
- else if (md->getGroupDef()!=0 && root->groups->count()==0)
- {
- //printf("existing member is grouped, new member not\n");
- root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri()));
- }
- else if (md->getGroupDef()!=0 && root->groups->getFirst()!=0)
- {
- //printf("both members are grouped\n");
- }
+ // merge ingroup specifiers
+ if (md->getGroupDef()==0 && root->groups->getFirst()!=0)
+ {
+ addMemberToGroups(root,md);
+ }
+ else if (md->getGroupDef()!=0 && root->groups->count()==0)
+ {
+ //printf("existing member is grouped, new member not\n");
+ root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri()));
+ }
+ else if (md->getGroupDef()!=0 && root->groups->getFirst()!=0)
+ {
+ //printf("both members are grouped\n");
+ }
- // if md is a declaration and root is the corresponding
- // definition, then turn md into a definition.
- if (md->isPrototype() && !root->proto)
- {
- md->setDeclFile(md->getDefFileName(),md->getDefLine(),md->getDefColumn());
- md->setPrototype(FALSE,root->fileName,root->startLine,root->startColumn);
- }
- // if md is already the definition, then add the declaration info
- else if (!md->isPrototype() && root->proto)
- {
- md->setDeclFile(root->fileName,root->startLine,root->startColumn);
+ // if md is a declaration and root is the corresponding
+ // definition, then turn md into a definition.
+ if (md->isPrototype() && !root->proto)
+ {
+ md->setDeclFile(md->getDefFileName(),md->getDefLine(),md->getDefColumn());
+ md->setPrototype(FALSE,root->fileName,root->startLine,root->startColumn);
+ }
+ // if md is already the definition, then add the declaration info
+ else if (!md->isPrototype() && root->proto)
+ {
+ md->setDeclFile(root->fileName,root->startLine,root->startColumn);
+ }
}
}
}
@@ -3870,24 +3930,27 @@ static void findFriends()
MemberDef *fmd;
for (;(fmd=fni.current());++fni) // for each function with that name
{
+ const MemberDef *cfmd = const_cast<const MemberDef*>(fmd);
MemberNameIterator mni(*mn);
MemberDef *mmd;
for (;(mmd=mni.current());++mni) // for each member with that name
{
+ const MemberDef *cmmd = const_cast<const MemberDef*>(mmd);
//printf("Checking for matching arguments
// mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
// mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
- ArgumentList *mmdAl = mmd->argumentList();
- ArgumentList *fmdAl = fmd->argumentList();
- if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
- matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), mmdAl,
- fmd->getOuterScope(), fmd->getFileDef(), fmdAl,
+ if ((cmmd->isFriend() || (cmmd->isRelated() && cmmd->isFunction())) &&
+ !fmd->isAlias() && !mmd->isAlias() &&
+ matchArguments2(cmmd->getOuterScope(), cmmd->getFileDef(), cmmd->argumentList(),
+ cfmd->getOuterScope(), cfmd->getFileDef(), cfmd->argumentList(),
TRUE
)
) // if the member is related and the arguments match then the
// function is actually a friend.
{
+ ArgumentList *mmdAl = mmd->argumentList();
+ ArgumentList *fmdAl = fmd->argumentList();
mergeArguments(mmdAl,fmdAl);
if (!fmd->documentation().isEmpty())
{
@@ -3968,7 +4031,10 @@ static void transferFunctionDocumentation()
MemberNameIterator mni2(*mn);
for (;(mdef=mni2.current());++mni2)
{
- combineDeclarationAndDefinition(mdec,mdef);
+ if (!mdec->isAlias() && !mdef->isAlias())
+ {
+ combineDeclarationAndDefinition(mdec,mdef);
+ }
}
}
}
@@ -4091,12 +4157,11 @@ static void transferRelatedFunctionDocumentation()
MemberNameIterator rmni(*rmn);
for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name
{
- ArgumentList *mdAl = md->argumentList();
- ArgumentList *rmdAl = rmd->argumentList();
//printf(" Member found: related=`%d'\n",rmd->isRelated());
if ((rmd->isRelated() || rmd->isForeign()) && // related function
- matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl,
- rmd->getOuterScope(),rmd->getFileDef(),rmdAl,
+ !md->isAlias() && !rmd->isAlias() &&
+ matchArguments2( md->getOuterScope(), md->getFileDef(), md->argumentList(),
+ rmd->getOuterScope(),rmd->getFileDef(),rmd->argumentList(),
TRUE
)
)
@@ -4165,11 +4230,11 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co
FileDef *fd=cd->getFileDef();
if (context && cd!=context)
{
- result = getResolvedClass(context,0,name,0,0,TRUE,TRUE);
+ result = const_cast<ClassDef*>(getResolvedClass(context,0,name,0,0,TRUE,TRUE));
}
if (result==0)
{
- result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE);
+ result = const_cast<ClassDef*>(getResolvedClass(cd,fd,name,0,0,TRUE,TRUE));
}
if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095)
{
@@ -4237,7 +4302,7 @@ static void findUsedClassesForClass(Entry *root,
while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1)
{
// find the type (if any) that matches usedClassName
- ClassDef *typeCd = getResolvedClass(masterCd,
+ const ClassDef *typeCd = getResolvedClass(masterCd,
masterCd->getFileDef(),
usedClassName,
0,0,
@@ -4638,16 +4703,17 @@ static bool findClassRelation(
//baseClassName=stripTemplateSpecifiersFromScope
// (removeRedundantWhiteSpace(baseClassName),TRUE,
// &stripped);
- MemberDef *baseClassTypeDef=0;
+ const MemberDef *baseClassTypeDef=0;
QCString templSpec;
- ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
+ ClassDef *baseClass=const_cast<ClassDef*>(
+ getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
cd->getFileDef(),
baseClassName,
&baseClassTypeDef,
&templSpec,
mode==Undocumented,
TRUE
- );
+ ));
//printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n",
// baseClassName.data(),baseClass,cd,explicitGlobalScope);
//printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
@@ -4698,14 +4764,15 @@ static bool findClassRelation(
{
templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i));
baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e);
- baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
- cd->getFileDef(),
- baseClassName,
- &baseClassTypeDef,
- 0, //&templSpec,
- mode==Undocumented,
- TRUE
- );
+ baseClass=const_cast<ClassDef*>(
+ getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
+ cd->getFileDef(),
+ baseClassName,
+ &baseClassTypeDef,
+ 0, //&templSpec,
+ mode==Undocumented,
+ TRUE
+ ));
//printf("baseClass=%p -> baseClass=%s templSpec=%s\n",
// baseClass,baseClassName.data(),templSpec.data());
}
@@ -4734,14 +4801,15 @@ static bool findClassRelation(
QCString tmpTemplSpec;
// replace any namespace aliases
replaceNamespaceAliases(baseClassName,si);
- baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
+ baseClass=const_cast<ClassDef*>(
+ getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
cd->getFileDef(),
baseClassName,
&baseClassTypeDef,
&tmpTemplSpec,
mode==Undocumented,
TRUE
- );
+ ));
found=baseClass!=0 && baseClass!=cd;
if (found) templSpec = tmpTemplSpec;
}
@@ -5183,7 +5251,10 @@ static void addListReferences()
ClassDef *cd=0;
for (cli.toFirst();(cd=cli.current());++cli)
{
- cd->addListReferences();
+ if (!cd->isAlias())
+ {
+ cd->addListReferences();
+ }
}
FileNameListIterator fnli(*Doxygen::inputNameList);
@@ -5202,7 +5273,10 @@ static void addListReferences()
NamespaceDef *nd=0;
for (nli.toFirst();(nd=nli.current());++nli)
{
- nd->addListReferences();
+ if (!nd->isAlias())
+ {
+ nd->addListReferences();
+ }
}
GroupSDict::Iterator gli(*Doxygen::groupSDict);
@@ -5281,8 +5355,8 @@ static void addMemberDocs(Entry *root,
md->enableCallerGraph(root->callerGraph);
md->enableReferencedByRelation(root->referencedByRelation);
md->enableReferencesRelation(root->referencesRelation);
- ClassDef *cd=md->getClassDef();
- NamespaceDef *nd=md->getNamespaceDef();
+ ClassDef *cd=md->getClassDef();
+ const NamespaceDef *nd=md->getNamespaceDef();
QCString fullName;
if (cd)
fullName = cd->name();
@@ -5407,10 +5481,10 @@ static void addMemberDocs(Entry *root,
// find a class definition given the scope name and (optionally) a
// template list specifier
-static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
+static const ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd,
const char *scopeName)
{
- ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE);
+ const ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE);
return tcd;
}
@@ -5448,12 +5522,20 @@ static bool findGlobalMember(Entry *root,
bool found=FALSE;
for (mni.toFirst();(md=mni.current()) && !found;++mni)
{
- NamespaceDef *nd=md->getNamespaceDef();
-
- //printf("Namespace namespaceName=%s nd=%s\n",
- // namespaceName.data(),nd ? nd->name().data() : "<none>");
+ const NamespaceDef *nd=0;
+ if (md->isAlias() && md->getOuterScope() &&
+ md->getOuterScope()->definitionType()==Definition::TypeNamespace)
+ {
+ nd = dynamic_cast<const NamespaceDef *>(md->getOuterScope());
+ }
+ else
+ {
+ nd = md->getNamespaceDef();
+ }
+ //const Definition *scope=md->getOuterScope();
+ //md = md->resolveAlias();
- FileDef *fd=root->fileDef();
+ const FileDef *fd=root->fileDef();
//printf("File %s\n",fd ? fd->name().data() : "<none>");
NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0;
//SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0;
@@ -5474,11 +5556,11 @@ static bool findGlobalMember(Entry *root,
NamespaceDef *rnd = 0;
if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName);
- ArgumentList *mdAl = md->argumentList();
+ const ArgumentList *mdAl = const_cast<const MemberDef *>(md)->argumentList();
bool matching=
(mdAl==0 && root->argList->count()==0) ||
md->isVariable() || md->isTypedef() || /* in case of function pointers */
- matchArguments2(md->getOuterScope(),md->getFileDef(),mdAl,
+ matchArguments2(md->getOuterScope(),const_cast<const MemberDef *>(md)->getFileDef(),mdAl,
rnd ? rnd : Doxygen::globalScope,fd,root->argList,
FALSE);
@@ -5487,7 +5569,7 @@ static bool findGlobalMember(Entry *root,
// different functions.
if (matching && root->tArgLists)
{
- ArgumentList *mdTempl = md->templateArguments();
+ const ArgumentList *mdTempl = md->templateArguments();
if (mdTempl)
{
if (root->tArgLists->getLast()->count()!=mdTempl->count())
@@ -5528,7 +5610,7 @@ static bool findGlobalMember(Entry *root,
if (matching) // add docs to the member
{
Debug::print(Debug::FindMembers,0,"5. Match found\n");
- addMemberDocs(root,md,decl,root->argList,FALSE);
+ addMemberDocs(root,md->resolveAlias(),decl,root->argList,FALSE);
found=TRUE;
}
}
@@ -5547,7 +5629,7 @@ static bool findGlobalMember(Entry *root,
warnMsg+=" '";
warnMsg+=substitute(md->declaration(),"%","%%");
warnMsg+="' at line "+QCString().setNum(md->getDefLine())+
- " of file"+md->getDefFileName()+"\n";
+ " of file "+md->getDefFileName()+"\n";
}
}
warn(root->fileName,root->startLine,warnMsg);
@@ -5587,12 +5669,12 @@ static bool isSpecialization(
return FALSE;
}
-static bool scopeIsTemplate(Definition *d)
+static bool scopeIsTemplate(const Definition *d)
{
bool result=FALSE;
if (d && d->definitionType()==Definition::TypeClass)
{
- result = (dynamic_cast<ClassDef*>(d))->templateArguments() || scopeIsTemplate(d->getOuterScope());
+ result = (dynamic_cast<const ClassDef*>(d))->templateArguments() || scopeIsTemplate(d->getOuterScope());
}
return result;
}
@@ -6089,7 +6171,7 @@ static void findMember(Entry *root,
//printf("scopeName %s->%s\n",scopeName.data(),
// stripTemplateSpecifiersFromScope(scopeName,FALSE).data());
- ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
+ const ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName)
{
// don't be fooled by anonymous scopes
@@ -6106,7 +6188,7 @@ static void findMember(Entry *root,
// get the template parameter lists found at the member declaration
QList<ArgumentList> declTemplArgs;
cd->getTemplateParameterLists(declTemplArgs);
- ArgumentList *templAl = md->templateArguments();
+ const ArgumentList *templAl = md->templateArguments();
if (templAl)
{
declTemplArgs.append(templAl);
@@ -6224,6 +6306,8 @@ static void findMember(Entry *root,
// TODO: copy other aspects?
root->protection=md->protection(); // copy protection level
+ root->stat=md->isStatic();
+ root->virt=md->virtualness();
addMethodToClass(root,cd,md->name(),isFriend);
return;
}
@@ -6251,7 +6335,7 @@ static void findMember(Entry *root,
if (count==0 && !(isFriend && funcType=="class"))
{
int candidates=0;
- ClassDef *ecd = 0, *ucd = 0;
+ const ClassDef *ecd = 0, *ucd = 0;
MemberDef *emd = 0, *umd = 0;
if (mn->count()>0)
{
@@ -6263,10 +6347,14 @@ static void findMember(Entry *root,
//printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data());
if (ccd!=0 && rightScopeMatch(ccd->name(),className))
{
- ArgumentList *templAl = md->templateArguments();
+ const ArgumentList *templAl = md->templateArguments();
if (root->tArgLists && templAl!=0 &&
root->tArgLists->getLast()->count()<=templAl->count())
{
+ Debug::print(Debug::FindMembers,0,"7. add template specialization\n");
+ root->protection=md->protection();
+ root->stat=md->isStatic();
+ root->virt=md->virtualness();
addMethodToClass(root,ccd,md->name(),isFriend);
return;
}
@@ -6337,10 +6425,10 @@ static void findMember(Entry *root,
warnMsg+="Possible candidates:\n";
for (mni.toFirst();(md=mni.current());++mni)
{
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
if (cd!=0 && rightScopeMatch(cd->name(),className))
{
- ArgumentList *templAl = md->templateArguments();
+ const ArgumentList *templAl = md->templateArguments();
if (templAl!=0)
{
warnMsg+=" 'template ";
@@ -6443,7 +6531,7 @@ static void findMember(Entry *root,
bool unique=TRUE;
for (;(md=mni.current());++mni)
{
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
if (className!=cd->name()) unique=FALSE;
}
if (unique)
@@ -6638,10 +6726,10 @@ static void findMember(Entry *root,
if (rmn)
{
MemberNameIterator rmni(*rmn);
- MemberDef *rmd;
+ const MemberDef *rmd;
while ((rmd=rmni.current()) && !found) // see if we got another member with matching arguments
{
- ArgumentList *rmdAl = rmd->argumentList();
+ const ArgumentList *rmdAl = rmd->argumentList();
// check for matching argument lists
if (
matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl,
@@ -7247,7 +7335,7 @@ static void addEnumValuesToEnums(Entry *root)
MemberDef *md;
for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list
{
- if (md->isEnumerate() && root->children())
+ if (!md->isAlias() && md->isEnumerate() && root->children())
{
//printf(" enum with %d children\n",root->children()->count());
EntryListIterator eli(*root->children()); // for each enum value
@@ -7335,7 +7423,7 @@ static void addEnumValuesToEnums(Entry *root)
// fmd->name().data(),fmd->getOuterScope()->name().data());
if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
{
- NamespaceDef *fnd=fmd->getNamespaceDef();
+ const NamespaceDef *fnd=fmd->getNamespaceDef();
if (fnd==nd) // enum value is inside a namespace
{
md->insertEnumField(fmd);
@@ -7344,7 +7432,7 @@ static void addEnumValuesToEnums(Entry *root)
}
else if (isGlobal)
{
- FileDef *ffd=fmd->getFileDef();
+ const FileDef *ffd=fmd->getFileDef();
if (ffd==fd) // enum value has file scope
{
md->insertEnumField(fmd);
@@ -7363,7 +7451,7 @@ static void addEnumValuesToEnums(Entry *root)
}
else
{
- ClassDef *fcd=fmd->getClassDef();
+ const ClassDef *fcd=fmd->getClassDef();
if (fcd==cd) // enum value is inside a class
{
//printf("Inserting enum field %s in enum scope %s\n",
@@ -7437,7 +7525,7 @@ static void findEnumDocumentation(Entry *root)
MemberDef *md;
for (mni.toFirst();(md=mni.current()) && !found;++mni)
{
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
if (cd && cd->name()==className && md->isEnumerate())
{
// documentation outside a compound overrides the documentation inside it
@@ -7471,7 +7559,7 @@ static void findEnumDocumentation(Entry *root)
md->addSectionsToDefinition(root->anchors);
md->setRefItems(root->sli);
- GroupDef *gd=md->getGroupDef();
+ const GroupDef *gd=md->getGroupDef();
if (gd==0 &&root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is
{
addMemberToGroups(root,md);
@@ -7505,7 +7593,7 @@ static void findEnumDocumentation(Entry *root)
md->addSectionsToDefinition(root->anchors);
md->setMemberGroupId(root->mGrpId);
- GroupDef *gd=md->getGroupDef();
+ const GroupDef *gd=md->getGroupDef();
if (gd==0 && root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is
{
addMemberToGroups(root,md);
@@ -7544,7 +7632,7 @@ static void findDEV(const MemberNameSDict &mnsd)
{
if (md->isEnumerate()) // member is an enum
{
- MemberList *fmdl = md->enumFieldList();
+ const MemberList *fmdl = md->enumFieldList();
int documentedEnumValues=0;
if (fmdl) // enum has values
{
@@ -7597,19 +7685,54 @@ static void addMembersToIndex()
// for each member definition
for (mni.toFirst();(md=mni.current());++mni)
{
- if (md->getNamespaceDef())
- {
- addNamespaceMemberNameToIndex(md);
- }
- else
+ if (!md->isAlias())
{
- addFileMemberNameToIndex(md);
+ if (md->getNamespaceDef())
+ {
+ addNamespaceMemberNameToIndex(md);
+ }
+ else
+ {
+ addFileMemberNameToIndex(md);
+ }
}
}
}
}
//----------------------------------------------------------------------
+
+static void vhdlCorrectMemberProperties()
+{
+ MemberName *mn;
+ MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
+ // for each member name
+ for (mnli.toFirst();(mn=mnli.current());++mnli)
+ {
+ MemberDef *md;
+ MemberNameIterator mni(*mn);
+ // for each member definition
+ for (mni.toFirst();(md=mni.current());++mni)
+ {
+ VhdlDocGen::correctMemberProperties(md);
+ }
+ }
+ MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
+ // for each member name
+ for (fnli.toFirst();(mn=fnli.current());++fnli)
+ {
+ MemberDef *md;
+ MemberNameIterator mni(*mn);
+ // for each member definition
+ for (mni.toFirst();(md=mni.current());++mni)
+ {
+ VhdlDocGen::correctMemberProperties(md);
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------
// computes the relation between all members. For each member `m'
// the members that override the implementation of `m' are searched and
// the member that `m' overrides is searched.
@@ -7628,10 +7751,10 @@ static void computeMemberRelations()
{
for ( bmdi.toFirst() ; (bmd=bmdi.current()); ++bmdi ) // for each other member with the same name
{
- ClassDef *mcd = md->getClassDef();
+ const ClassDef *mcd = md->getClassDef();
if (mcd && mcd->baseClasses())
{
- ClassDef *bmcd = bmd->getClassDef();
+ const ClassDef *bmcd = bmd->getClassDef();
//printf("Check relation between `%s'::`%s' (%p) and `%s'::`%s' (%p)\n",
// mcd->name().data(),md->name().data(),md,
// bmcd->name().data(),bmd->name().data(),bmd
@@ -7856,7 +7979,7 @@ static void generateFileSources()
{
QStrList filesInSameTu;
fd->startParsing();
- if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
+ if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output
{
msg("Generating code for file %s...\n",fd->docName().data());
fd->writeSource(*g_outputList,FALSE,filesInSameTu);
@@ -7886,7 +8009,7 @@ static void generateFileSources()
{
QStrList filesInSameTu;
fd->startParsing();
- if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
+ if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output
{
msg("Generating code for file %s...\n",fd->docName().data());
fd->writeSource(*g_outputList,FALSE,filesInSameTu);
@@ -8055,6 +8178,85 @@ static void sortMemberLists()
}
//----------------------------------------------------------------------------
+
+static void setAnonymousEnumType()
+{
+ ClassSDict::Iterator cli(*Doxygen::classSDict);
+ ClassDef *cd=0;
+ for (cli.toFirst();(cd=cli.current());++cli)
+ {
+ cd->setAnonymousEnumType();
+ }
+
+#if 0
+ NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
+ NamespaceDef *nd=0;
+ for (nli.toFirst();(nd=nli.current());++nli)
+ {
+ nd->setAnonymousEnumType();
+ }
+
+ FileNameListIterator fnli(*Doxygen::inputNameList);
+ FileName *fn;
+ for (;(fn=fnli.current());++fnli)
+ {
+ FileNameIterator fni(*fn);
+ FileDef *fd;
+ for (;(fd=fni.current());++fni)
+ {
+ fd->setAnonymousEnumType();
+ }
+ }
+
+ GroupSDict::Iterator gli(*Doxygen::groupSDict);
+ GroupDef *gd;
+ for (gli.toFirst();(gd=gli.current());++gli)
+ {
+ gd->setAnonymousEnumType();
+ }
+#endif
+}
+
+//----------------------------------------------------------------------------
+
+static void countMembers()
+{
+ ClassSDict::Iterator cli(*Doxygen::classSDict);
+ ClassDef *cd=0;
+ for (cli.toFirst();(cd=cli.current());++cli)
+ {
+ cd->countMembers();
+ }
+
+ NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
+ NamespaceDef *nd=0;
+ for (nli.toFirst();(nd=nli.current());++nli)
+ {
+ nd->countMembers();
+ }
+
+ FileNameListIterator fnli(*Doxygen::inputNameList);
+ FileName *fn;
+ for (;(fn=fnli.current());++fnli)
+ {
+ FileNameIterator fni(*fn);
+ FileDef *fd;
+ for (;(fd=fni.current());++fni)
+ {
+ fd->countMembers();
+ }
+ }
+
+ GroupSDict::Iterator gli(*Doxygen::groupSDict);
+ GroupDef *gd;
+ for (gli.toFirst();(gd=gli.current());++gli)
+ {
+ gd->countMembers();
+ }
+}
+
+
+//----------------------------------------------------------------------------
// generate the documentation of all classes
static void generateClassList(ClassSDict &classSDict)
@@ -8321,7 +8523,7 @@ static void flushCachedTemplateRelations()
{
if (fmd->isTypedefValCached())
{
- ClassDef *cd = fmd->getCachedTypedefVal();
+ const ClassDef *cd = fmd->getCachedTypedefVal();
if (cd->isTemplate()) fmd->invalidateTypedefValCache();
}
}
@@ -8335,7 +8537,7 @@ static void flushCachedTemplateRelations()
{
if (fmd->isTypedefValCached())
{
- ClassDef *cd = fmd->getCachedTypedefVal();
+ const ClassDef *cd = fmd->getCachedTypedefVal();
if (cd->isTemplate()) fmd->invalidateTypedefValCache();
}
}
@@ -8469,7 +8671,7 @@ static void findDefineDocumentation(Entry *root)
{
if (md->memberType()==MemberType_Define)
{
- FileDef *fd=md->getFileDef();
+ const FileDef *fd=md->getFileDef();
if (fd && fd->absFilePath()==root->fileName)
// doc and define in the same file assume they belong together.
{
@@ -8792,7 +8994,7 @@ static void resolveUserReferences()
{
// TODO: there should be one function in Definition that returns
// the file to link to, so we can avoid the following tests.
- GroupDef *gd=0;
+ const GroupDef *gd=0;
if (si->definition->definitionType()==Definition::TypeMember)
{
gd = (dynamic_cast<MemberDef *>(si->definition))->getGroupDef();
@@ -9956,7 +10158,7 @@ static void usage(const char *name)
msg(" RTF: %s -e rtf extensionsFile\n\n",name);
msg("7) Use doxygen to compare the used configuration file with the template configuration file\n");
msg(" %s -x [configFile]\n\n",name);
- msg("8) Use doxygen to show a list of build in emoji.\n");
+ msg("8) Use doxygen to show a list of built-in emojis.\n");
msg(" %s -f emoji outputFileName\n\n",name);
msg(" If - is used for outputFileName doxygen will write to standard output.\n\n");
msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n");
@@ -11094,9 +11296,7 @@ void parseInput()
if (layoutFile.open(IO_ReadOnly))
{
msg("Parsing layout file %s...\n",layoutFileName.data());
- QTextStream t(&layoutFile);
- t.setEncoding(QTextStream::Latin1);
- LayoutDocManager::instance().parse(t,layoutFileName);
+ LayoutDocManager::instance().parse(layoutFileName);
}
else if (!defaultLayoutUsed)
{
@@ -11198,9 +11398,6 @@ void parseInput()
buildClassList(root);
g_s.end();
- g_s.begin("Associating documentation with classes...\n");
- buildClassDocList(root);
-
// build list of using declarations here (global list)
buildListOfUsingDecls(root);
g_s.end();
@@ -11218,6 +11415,9 @@ void parseInput()
// we don't need the list of using declaration anymore
g_usingDeclarations.clear();
+ g_s.begin("Associating documentation with classes...\n");
+ buildClassDocList(root);
+
g_s.begin("Building example list...\n");
buildExampleList(root);
g_s.end();
@@ -11407,6 +11607,10 @@ void parseInput()
sortMemberLists();
g_s.end();
+ g_s.begin("Setting anonymous enum type...\n");
+ setAnonymousEnumType();
+ g_s.end();
+
if (Config_getBool(DIRECTORY_GRAPH))
{
g_s.begin("Computing dependencies between directories...\n");
@@ -11421,6 +11625,10 @@ void parseInput()
Doxygen::citeDict->generatePage();
g_s.end();
+ g_s.begin("Counting members...\n");
+ countMembers();
+ g_s.end();
+
g_s.begin("Counting data structures...\n");
countDataStructures();
g_s.end();
@@ -11444,6 +11652,11 @@ void parseInput()
g_s.begin("Adding members to index pages...\n");
addMembersToIndex();
g_s.end();
+
+ g_s.begin("Correcting members for VHDL...\n");
+ vhdlCorrectMemberProperties();
+ g_s.end();
+
}
void generateOutput()
@@ -11463,6 +11676,7 @@ void generateOutput()
}
initSearchIndexer();
+ initDot();
bool generateHtml = Config_getBool(GENERATE_HTML);
bool generateLatex = Config_getBool(GENERATE_LATEX);
@@ -11517,7 +11731,7 @@ void generateOutput()
QCString htmldir = Config_getString(HTML_OUTPUT);
if (!Htags::execute(htmldir))
err("USE_HTAGS is YES but htags(1) failed. \n");
- if (!Htags::loadFilemap(htmldir))
+ else if (!Htags::loadFilemap(htmldir))
err("htags(1) ended normally but failed to load the filemap. \n");
}
@@ -11564,12 +11778,9 @@ void generateOutput()
generateExampleDocs();
g_s.end();
- if (!Htags::useHtags)
- {
- g_s.begin("Generating file sources...\n");
- generateFileSources();
- g_s.end();
- }
+ g_s.begin("Generating file sources...\n");
+ generateFileSources();
+ g_s.end();
g_s.begin("Generating file documentation...\n");
generateFileDocs();
diff --git a/src/doxygen.h b/src/doxygen.h
index 4ff8a56..c8eee7c 100644
--- a/src/doxygen.h
+++ b/src/doxygen.h
@@ -27,6 +27,7 @@
#include "membergroup.h"
#include "dirdef.h"
#include "memberlist.h"
+#include "docgroup.h"
class RefList;
class PageSList;
@@ -76,10 +77,10 @@ class StringDict : public QDict<QCString>
struct LookupInfo
{
LookupInfo() : classDef(0), typeDef(0) {}
- LookupInfo(ClassDef *cd,MemberDef *td,QCString ts,QCString rt)
+ LookupInfo(const ClassDef *cd,const MemberDef *td,QCString ts,QCString rt)
: classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {}
- ClassDef *classDef;
- MemberDef *typeDef;
+ const ClassDef *classDef;
+ const MemberDef *typeDef;
QCString templSpec;
QCString resolvedType;
};
@@ -150,6 +151,7 @@ class Doxygen
static bool generatingXmlOutput;
static bool markdownSupport;
static GenericsSDict *genericsDict;
+ static DocGroup docGroup;
};
void initDoxygen();
diff --git a/src/eclipsehelp.cpp b/src/eclipsehelp.cpp
index bf150b4..dab001a 100644
--- a/src/eclipsehelp.cpp
+++ b/src/eclipsehelp.cpp
@@ -174,7 +174,7 @@ void EclipseHelp::addContentsItem(
const char *anchor,
bool /* separateIndex */,
bool /* addToNavIndex */,
- Definition * /*def*/)
+ const Definition * /*def*/)
{
// -- write the topic tag
closedTag();
@@ -216,8 +216,8 @@ void EclipseHelp::addContentsItem(
}
void EclipseHelp::addIndexItem(
- Definition * /* context */,
- MemberDef * /* md */,
+ const Definition * /* context */,
+ const MemberDef * /* md */,
const char * /* sectionAnchor */,
const char * /* title */)
{
diff --git a/src/eclipsehelp.h b/src/eclipsehelp.h
index a7cde1e..5d63768 100644
--- a/src/eclipsehelp.h
+++ b/src/eclipsehelp.h
@@ -50,8 +50,8 @@ class EclipseHelp : public IndexIntf
virtual void decContentsDepth();
virtual void addContentsItem(bool isDir, const char *name, const char *ref,
const char *file, const char *anchor,bool separateIndex,bool addToNavIndex,
- Definition *def);
- virtual void addIndexItem(Definition *context,MemberDef *md,
+ const Definition *def);
+ virtual void addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor,const char *title);
virtual void addIndexFile(const char *name);
virtual void addImageFile(const char *name);
diff --git a/src/entry.h b/src/entry.h
index 8810c18..6dfa0c6 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -186,7 +186,7 @@ class Entry
enum GroupDocType
{
GROUPDOC_NORMAL, //!< defgroup
- GROUPDOC_ADD, //!< addgroup
+ GROUPDOC_ADD, //!< addtogroup
GROUPDOC_WEAK //!< weakgroup
}; //!< kind of group
@@ -301,7 +301,7 @@ class Entry
switch( groupDocType )
{
case GROUPDOC_NORMAL: return "\\defgroup";
- case GROUPDOC_ADD: return "\\addgroup";
+ case GROUPDOC_ADD: return "\\addtogroup";
case GROUPDOC_WEAK: return "\\weakgroup";
default: return "unknown group command";
}
diff --git a/src/filedef.cpp b/src/filedef.cpp
index 130679e..7a3323d 100644
--- a/src/filedef.cpp
+++ b/src/filedef.cpp
@@ -26,6 +26,7 @@
#include "language.h"
#include "outputlist.h"
#include "dot.h"
+#include "dotincldepgraph.h"
#include "message.h"
#include "docparser.h"
#include "searchindex.h"
@@ -90,11 +91,14 @@ class FileDefImpl : public DefinitionImpl, public FileDef
virtual bool hasDetailedDescription() const;
virtual QCString fileVersion() const;
virtual bool subGrouping() const { return m_subGrouping; }
+ virtual void countMembers();
+ virtual int numDocMembers() const;
+ virtual int numDecMembers() const;
virtual void addSourceRef(int line,Definition *d,MemberDef *md);
virtual void writeDocumentation(OutputList &ol);
virtual void writeMemberPages(OutputList &ol);
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const;
- virtual void writeSummaryLinks(OutputList &ol);
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const;
+ virtual void writeSummaryLinks(OutputList &ol) const;
virtual void writeTagFile(FTextStream &t);
virtual void startParsing();
virtual void writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu);
@@ -107,7 +111,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef
virtual void computeAnchors();
virtual void setPackageDef(PackageDef *pd) { m_package=pd; }
virtual void setDirDef(DirDef *dd) { m_dir=dd; }
- virtual void addUsingDirective(NamespaceDef *nd);
+ virtual void addUsingDirective(const NamespaceDef *nd);
virtual void addUsingDeclaration(Definition *def);
virtual void combineUsingRelations();
virtual bool generateSourceFile() const;
@@ -203,7 +207,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface
virtual void endFontClass() {}
virtual void writeCodeAnchor(const char *) {}
virtual void linkableSymbol(int, const char *,Definition *,Definition *) {}
- virtual void setCurrentDoc(Definition *,const char *,bool) {}
+ virtual void setCurrentDoc(const Definition *,const char *,bool) {}
virtual void addWord(const char *,bool) {}
};
@@ -801,7 +805,7 @@ void FileDefImpl::writeAuthorSection(OutputList &ol)
ol.popGeneratorState();
}
-void FileDefImpl::writeSummaryLinks(OutputList &ol)
+void FileDefImpl::writeSummaryLinks(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
@@ -1103,7 +1107,7 @@ void FileDefImpl::writeMemberPages(OutputList &ol)
ol.popGeneratorState();
}
-void FileDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
+void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const
{
static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
@@ -1503,7 +1507,7 @@ MemberDef *FileDefImpl::getSourceMember(int lineNr) const
}
-void FileDefImpl::addUsingDirective(NamespaceDef *nd)
+void FileDefImpl::addUsingDirective(const NamespaceDef *nd)
{
if (m_usingDirList==0)
{
@@ -2210,3 +2214,36 @@ QCString FileDefImpl::includedByDependencyGraphFileName() const
return m_inclByDepFileName;
}
+void FileDefImpl::countMembers()
+{
+ QListIterator<MemberList> mli(m_memberLists);
+ MemberList *ml;
+ for (mli.toFirst();(ml=mli.current());++mli)
+ {
+ ml->countDecMembers();
+ ml->countDocMembers();
+ }
+ if (m_memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*m_memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->countDecMembers();
+ mg->countDocMembers();
+ }
+ }
+}
+
+int FileDefImpl::numDocMembers() const
+{
+ MemberList *ml = getMemberList(MemberListType_allMembersList);
+ return ml ? ml->numDocMembers() : 0;
+}
+
+int FileDefImpl::numDecMembers() const
+{
+ MemberList *ml = getMemberList(MemberListType_allMembersList);
+ return ml ? ml->numDecMembers() : 0;
+}
+
diff --git a/src/filedef.h b/src/filedef.h
index 63cacf5..b66d7be 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -135,14 +135,18 @@ class FileDef : virtual public Definition
virtual bool subGrouping() const = 0;
+ virtual void countMembers() = 0;
+ virtual int numDocMembers() const = 0;
+ virtual int numDecMembers() const = 0;
+
//---------------------------------
virtual void addSourceRef(int line,Definition *d,MemberDef *md) = 0;
virtual void writeDocumentation(OutputList &ol) = 0;
virtual void writeMemberPages(OutputList &ol) = 0;
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0;
- virtual void writeSummaryLinks(OutputList &ol) = 0;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0;
+ virtual void writeSummaryLinks(OutputList &ol) const = 0;
virtual void writeTagFile(FTextStream &t) = 0;
virtual void startParsing() = 0;
@@ -159,7 +163,7 @@ class FileDef : virtual public Definition
virtual void setPackageDef(PackageDef *pd) = 0;
virtual void setDirDef(DirDef *dd) = 0;
- virtual void addUsingDirective(NamespaceDef *nd) = 0;
+ virtual void addUsingDirective(const NamespaceDef *nd) = 0;
virtual void addUsingDeclaration(Definition *def) = 0;
virtual void combineUsingRelations() = 0;
diff --git a/src/fileparser.cpp b/src/fileparser.cpp
index 6883622..45bdc81 100644
--- a/src/fileparser.cpp
+++ b/src/fileparser.cpp
@@ -26,9 +26,9 @@ void FileParser::parseCode(CodeOutputInterface &codeOutIntf,
int startLine,
int endLine,
bool, // inlineFragment
- MemberDef *, // memberDef
+ const MemberDef *, // memberDef
bool showLineNumbers,
- Definition *, // searchCtx,
+ const Definition *, // searchCtx,
bool // collectXRefs
)
{
diff --git a/src/fileparser.h b/src/fileparser.h
index 4568a39..4b311e6 100644
--- a/src/fileparser.h
+++ b/src/fileparser.h
@@ -37,9 +37,9 @@ class FileParser : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
void resetCodeParserState() {}
diff --git a/src/fortrancode.h b/src/fortrancode.h
index c110852..4df20a9 100644
--- a/src/fortrancode.h
+++ b/src/fortrancode.h
@@ -29,7 +29,7 @@ class Definition;
void parseFortranCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectRefs, FortranFormat format);
void resetFortranCodeParserState();
void codeFreeScanner();
diff --git a/src/fortrancode.l b/src/fortrancode.l
index 31924fa..926a3ff 100644
--- a/src/fortrancode.l
+++ b/src/fortrancode.l
@@ -140,7 +140,7 @@ static int g_yyLineNr; //!< current line number
static int g_contLineNr; //!< current, local, line number for continuation determination
static int *g_hasContLine = NULL; //!< signals whether or not a line has a continuation line (fixed source form)
static bool g_needsTermination;
-static Definition *g_searchCtx;
+static const Definition *g_searchCtx;
static bool g_collectXRefs;
static bool g_isFixedForm;
@@ -452,16 +452,16 @@ static bool getFortranDefs(const QCString &memberName, const QCString &moduleNam
MemberNameIterator mli(*mn);
for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name
{
- FileDef *fd=md->getFileDef();
- GroupDef *gd=md->getGroupDef();
- ClassDef *cd=md->getClassDef();
+ const FileDef *fd=md->getFileDef();
+ const GroupDef *gd=md->getGroupDef();
+ const ClassDef *cd=md->getClassDef();
//cout << "found link with same name: " << fd->fileName() << " " << memberName;
//if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl;
if ((gd && gd->isLinkable()) || (fd && fd->isLinkable()))
{
- NamespaceDef *nspace= md->getNamespaceDef();
+ const NamespaceDef *nspace= md->getNamespaceDef();
if (nspace == 0)
{ // found function in global scope
@@ -532,8 +532,8 @@ static bool getLink(UseSDict *usedict, // dictonary with used modules
if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet,
// see also linkifyText in util.cpp
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable())
{
@@ -1313,18 +1313,14 @@ static void checkContLines(const char *s)
g_hasContLine[0] = 0;
}
-void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s,
+void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s,
bool exBlock, const char *exName,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool,Definition *searchCtx,
+ const MemberDef *,bool,const Definition *searchCtx,
bool collectXRefs, FortranFormat format)
{
//printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
- // used parameters
- (void)memberDef;
- (void)className;
-
if (s.isEmpty()) return;
printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
g_code = &od;
diff --git a/src/fortranscanner.h b/src/fortranscanner.h
index bc8071b..15a9bf0 100644
--- a/src/fortranscanner.h
+++ b/src/fortranscanner.h
@@ -47,9 +47,9 @@ class FortranLanguageScanner : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
void resetCodeParserState();
diff --git a/src/fortranscanner.l b/src/fortranscanner.l
index 7d7437d..1076e68 100644
--- a/src/fortranscanner.l
+++ b/src/fortranscanner.l
@@ -698,6 +698,14 @@ private {
typeMode = false;
yy_pop_state();
}
+^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */
+ warn(yyFileName,yyLineNr, "Found 'END' instead of 'END TYPE'");
+ last_entry->parent()->endBodyLine = yyLineNr;
+ if (!endScope(current_root))
+ yyterminate();
+ typeMode = false;
+ yy_pop_state();
+ }
}
/*------- module/global/typedef variable ---------------------------------------------------*/
@@ -2296,7 +2304,7 @@ static void initEntry()
current->virt = virt;
current->stat = gstat;
current->lang = SrcLangExt_Fortran;
- initGroupInfo(current);
+ Doxygen::docGroup.initGroupInfo(current);
}
/**
@@ -2704,7 +2712,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
global_scope = rt;
startScope(rt); // implies current_root = rt
initParser();
- groupEnterFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.enterFile(yyFileName,yyLineNr);
current = new Entry;
current->lang = SrcLangExt_Fortran;
@@ -2721,7 +2729,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
}
fortranscannerYYlex();
- groupLeaveFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.leaveFile(yyFileName,yyLineNr);
if (global_scope && global_scope != (Entry *) -1) endScope(current_root, TRUE); // TRUE - global root
@@ -2770,9 +2778,9 @@ void FortranLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
@@ -2819,7 +2827,7 @@ static void scanner_abort()
// dummy call to avoid compiler warning
(void)yy_top_state();
-
+
return;
//exit(-1);
}
diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp
index d66a935..149f43c 100644
--- a/src/ftvhelp.cpp
+++ b/src/ftvhelp.cpp
@@ -46,7 +46,7 @@ static int folderId=1;
struct FTVNode
{
FTVNode(bool dir,const char *r,const char *f,const char *a,
- const char *n,bool sepIndex,bool navIndex,Definition *df)
+ const char *n,bool sepIndex,bool navIndex,const Definition *df)
: isLast(TRUE), isDir(dir),ref(r),file(f),anchor(a),name(n), index(0),
parent(0), separateIndex(sepIndex), addToNavIndex(navIndex),
def(df) { children.setAutoDelete(TRUE); }
@@ -63,7 +63,7 @@ struct FTVNode
FTVNode *parent;
bool separateIndex;
bool addToNavIndex;
- Definition *def;
+ const Definition *def;
};
int FTVNode::computeTreeDepth(int level) const
@@ -187,7 +187,7 @@ void FTVHelp::addContentsItem(bool isDir,
const char *anchor,
bool separateIndex,
bool addToNavIndex,
- Definition *def
+ const Definition *def
)
{
//printf("%p: m_indent=%d addContentsItem(%s,%s,%s,%s)\n",this,m_indent,name,ref,file,anchor);
@@ -207,7 +207,7 @@ void FTVHelp::addContentsItem(bool isDir,
}
-static QCString node2URL(FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE)
+static QCString node2URL(const FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE)
{
QCString url = n->file;
if (!url.isEmpty() && url.at(0)=='!') // relative URL
@@ -223,7 +223,7 @@ static QCString node2URL(FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE)
{
if (overruleFile && n->def && n->def->definitionType()==Definition::TypeFile)
{
- FileDef *fd = dynamic_cast<FileDef*>(n->def);
+ const FileDef *fd = dynamic_cast<const FileDef*>(n->def);
if (srcLink)
{
url = fd->getSourceFileBase();
@@ -315,7 +315,7 @@ void FTVHelp::generateLink(FTextStream &t,FTVNode *n)
}
}
-static void generateBriefDoc(FTextStream &t,Definition *def)
+static void generateBriefDoc(FTextStream &t,const Definition *def)
{
QCString brief = def->briefDescription(TRUE);
//printf("*** %p: generateBriefDoc(%s)='%s'\n",def,def->name().data(),brief.data());
@@ -332,7 +332,7 @@ static void generateBriefDoc(FTextStream &t,Definition *def)
}
}
-static char compoundIcon(ClassDef *cd)
+static char compoundIcon(const ClassDef *cd)
{
char icon='C';
if (cd->getLanguage() == SrcLangExt_Slice)
@@ -392,7 +392,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in
}
else if (n->def && n->def->definitionType()==Definition::TypeClass)
{
- char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def));
+ char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def));
t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
}
else
@@ -415,11 +415,11 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in
}
else // leaf node
{
- FileDef *srcRef=0;
+ const FileDef *srcRef=0;
if (n->def && n->def->definitionType()==Definition::TypeFile &&
- (dynamic_cast<FileDef*>(n->def))->generateSourceFile())
+ (dynamic_cast<const FileDef*>(n->def))->generateSourceFile())
{
- srcRef = dynamic_cast<FileDef*>(n->def);
+ srcRef = dynamic_cast<const FileDef*>(n->def);
}
if (srcRef)
{
@@ -448,7 +448,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in
}
else if (n->def && n->def->definitionType()==Definition::TypeClass)
{
- char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def));
+ char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def));
t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>";
}
else
@@ -492,7 +492,7 @@ class NavIndexEntryList : public QList<NavIndexEntry>
}
};
-static QCString pathToNode(FTVNode *leaf,FTVNode *n)
+static QCString pathToNode(const FTVNode *leaf,const FTVNode *n)
{
QCString result;
if (n->parent)
@@ -511,7 +511,7 @@ static bool dupOfParent(const FTVNode *n)
return FALSE;
}
-static void generateJSLink(FTextStream &t,FTVNode *n)
+static void generateJSLink(FTextStream &t,const FTVNode *n)
{
if (n->file.isEmpty()) // no link
{
@@ -542,7 +542,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t,
indentStr.fill(' ',level*2);
bool found=FALSE;
QListIterator<FTVNode> nli(nl);
- FTVNode *n;
+ const FTVNode *n;
for (nli.toFirst();(n=nli.current());++nli)
{
// terminate previous entry
@@ -560,7 +560,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t,
{
if (n->def && n->def->definitionType()==Definition::TypeFile)
{
- FileDef *fd = dynamic_cast<FileDef*>(n->def);
+ const FileDef *fd = dynamic_cast<const FileDef*>(n->def);
bool doc,src;
doc = fileVisibleInIndex(fd,src);
if (doc)
diff --git a/src/ftvhelp.h b/src/ftvhelp.h
index eac0367..4c3f986 100644
--- a/src/ftvhelp.h
+++ b/src/ftvhelp.h
@@ -50,8 +50,8 @@ class FTVHelp : public IndexIntf
const char *anchor,
bool separateIndex,
bool addToNavIndex,
- Definition *def);
- void addIndexItem(Definition *,MemberDef *,const char *,const char *) {}
+ const Definition *def);
+ void addIndexItem(const Definition *,const MemberDef *,const char *,const char *) {}
void addIndexFile(const char *) {}
void addImageFile(const char *) {}
void addStyleSheetFile(const char *) {}
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
index 31eb7fe..9525053 100644
--- a/src/groupdef.cpp
+++ b/src/groupdef.cpp
@@ -33,6 +33,7 @@
#include "docparser.h"
#include "searchindex.h"
#include "dot.h"
+#include "dotgroupcollaboration.h"
#include "vhdldocgen.h"
#include "layout.h"
#include "arguments.h"
@@ -69,13 +70,14 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef
virtual bool findGroup(const GroupDef *def) const; // true if def is a subgroup of this group
virtual void writeDocumentation(OutputList &ol);
virtual void writeMemberPages(OutputList &ol);
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const;
virtual void writeTagFile(FTextStream &);
- virtual int countMembers() const;
+ virtual int numDocMembers() const;
virtual bool isLinkableInProject() const;
virtual bool isLinkable() const;
virtual bool isASubGroup() const;
virtual void computeAnchors();
+ virtual void countMembers();
virtual void addMembersToMemberGroup();
virtual void distributeMemberGroupDocumentation();
@@ -127,7 +129,7 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef
void startMemberDocumentation(OutputList &ol);
void endMemberDocumentation(OutputList &ol);
void writeAuthorSection(OutputList &ol);
- void writeSummaryLinks(OutputList &ol);
+ void writeSummaryLinks(OutputList &ol) const;
void updateLanguage(const Definition *);
QCString title; // title of the group
@@ -383,10 +385,10 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly)
if ((mni=(*allMemberNameInfoSDict)[md->name()]))
{ // member with this name already found
MemberNameInfoIterator srcMnii(*mni);
- MemberInfo *srcMi;
+ const MemberInfo *srcMi;
for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
{
- MemberDef *srcMd = srcMi->memberDef;
+ const MemberDef *srcMd = srcMi->memberDef;
if (srcMd==md) return FALSE; // already added before!
bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace
@@ -394,10 +396,10 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly)
(srcMd->getOuterScope()->definitionType()==Definition::TypeFile &&
md->getOuterScope()->definitionType()==Definition::TypeFile);
- ArgumentList *srcMdAl = srcMd->argumentList();
- ArgumentList *mdAl = md->argumentList();
- ArgumentList *tSrcMdAl = srcMd->templateArguments();
- ArgumentList *tMdAl = md->templateArguments();
+ const ArgumentList *srcMdAl = srcMd->argumentList();
+ const ArgumentList *mdAl = md->argumentList();
+ const ArgumentList *tSrcMdAl = srcMd->templateArguments();
+ const ArgumentList *tMdAl = md->templateArguments();
if (srcMd->isFunction() && md->isFunction() && // both are a function
((tSrcMdAl==0 && tMdAl==0) ||
@@ -662,7 +664,28 @@ bool GroupDefImpl::isASubGroup() const
return groups!=0 && groups->count()!=0;
}
-int GroupDefImpl::countMembers() const
+void GroupDefImpl::countMembers()
+{
+ QListIterator<MemberList> mli(m_memberLists);
+ MemberList *ml;
+ for (;(ml=mli.current());++mli)
+ {
+ ml->countDecMembers();
+ ml->countDocMembers();
+ }
+ if (memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->countDecMembers();
+ mg->countDocMembers();
+ }
+ }
+}
+
+int GroupDefImpl::numDocMembers() const
{
return fileList->count()+
classSDict->count()+
@@ -830,7 +853,7 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title
)
{
ol.pushGeneratorState();
- if (pageDict->count()!=countMembers()) // not only pages -> classical layout
+ if (pageDict->count()!=numDocMembers()) // not only pages -> classical layout
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Html);
@@ -1154,7 +1177,7 @@ void GroupDefImpl::writeAuthorSection(OutputList &ol)
ol.popGeneratorState();
}
-void GroupDefImpl::writeSummaryLinks(OutputList &ol)
+void GroupDefImpl::writeSummaryLinks(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
@@ -1394,7 +1417,7 @@ void GroupDefImpl::writeMemberPages(OutputList &ol)
ol.popGeneratorState();
}
-void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
+void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const
{
static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
@@ -1557,7 +1580,7 @@ void addMemberToGroups(Entry *root,MemberDef *md)
// put member into group defined by this entry?
if (fgd)
{
- GroupDef *mgd = md->getGroupDef();
+ GroupDef *mgd = const_cast<GroupDef*>(md->getGroupDef());
//printf("mgd=%p\n",mgd);
bool insertit = FALSE;
if (mgd==0)
diff --git a/src/groupdef.h b/src/groupdef.h
index 2649de7..92d524f 100644
--- a/src/groupdef.h
+++ b/src/groupdef.h
@@ -66,13 +66,14 @@ class GroupDef : virtual public Definition
virtual bool findGroup(const GroupDef *def) const = 0;
virtual void writeDocumentation(OutputList &ol) = 0;
virtual void writeMemberPages(OutputList &ol) = 0;
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0;
virtual void writeTagFile(FTextStream &) = 0;
- virtual int countMembers() const = 0;
+ virtual int numDocMembers() const = 0;
virtual bool isLinkableInProject() const = 0;
virtual bool isLinkable() const = 0;
virtual bool isASubGroup() const = 0;
virtual void computeAnchors() = 0;
+ virtual void countMembers() = 0;
virtual void addMembersToMemberGroup() = 0;
virtual void distributeMemberGroupDocumentation() = 0;
diff --git a/src/htags.cpp b/src/htags.cpp
index 77b1f8d..51cd6d9 100644
--- a/src/htags.cpp
+++ b/src/htags.cpp
@@ -91,6 +91,10 @@ bool Htags::execute(const QCString &htmldir)
//printf("CommandLine=[%s]\n",commandLine.data());
portable_sysTimerStart();
bool result=portable_system("htags",commandLine,FALSE)==0;
+ if (!result)
+ {
+ err("Problems running %s. Check your installation\n", "htags");
+ }
portable_sysTimerStop();
QDir::setCurrent(oldDir);
return result;
@@ -128,7 +132,7 @@ bool Htags::loadFilemap(const QCString &htmlDir)
int len;
while ((len=f.readLine(line.rawData(),maxlen))>0)
{
- line.resize(len+1);
+ line.at(len)='\0';
//printf("Read line: %s",line.data());
int sep = line.find('\t');
if (sep!=-1)
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index 37f6bd0..05cdc42 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -270,7 +270,7 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl
//-------------------------------------------------------------------------
HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,
- Definition *ctx)
+ const Definition *ctx)
: DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE),
m_hide(FALSE), m_ctx(ctx)
{
@@ -784,19 +784,21 @@ void HtmlDocVisitor::visit(DocIncOperator *op)
pushEnabled();
m_hide=TRUE;
}
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
if (op->type()!=DocIncOperator::Skip)
{
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(
m_ci,
op->context(),
@@ -2116,14 +2118,6 @@ void HtmlDocVisitor::visitPost(DocInternalRef *)
m_t << " ";
}
-void HtmlDocVisitor::visitPre(DocCopy *)
-{
-}
-
-void HtmlDocVisitor::visitPost(DocCopy *)
-{
-}
-
void HtmlDocVisitor::visitPre(DocText *)
{
}
diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h
index 7184f0f..c994bac 100644
--- a/src/htmldocvisitor.h
+++ b/src/htmldocvisitor.h
@@ -33,7 +33,7 @@ class CodeOutputInterface;
class HtmlDocVisitor : public DocVisitor
{
public:
- HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,Definition *ctx);
+ HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,const Definition *ctx);
//--------------------------------------
// visitor functions for leaf nodes
@@ -127,8 +127,6 @@ class HtmlDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
@@ -171,7 +169,7 @@ class HtmlDocVisitor : public DocVisitor
bool m_insidePre;
bool m_hide;
QStack<bool> m_enabled;
- Definition *m_ctx;
+ const Definition *m_ctx;
QCString m_langExt;
};
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index cd45e5f..402b4e4 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -28,6 +28,12 @@
#include "diagram.h"
#include "version.h"
#include "dot.h"
+#include "dotcallgraph.h"
+#include "dotclassgraph.h"
+#include "dotdirdeps.h"
+#include "dotgfxhierarchytable.h"
+#include "dotgroupcollaboration.h"
+#include "dotincldepgraph.h"
#include "language.h"
#include "htmlhelp.h"
#include "docparser.h"
@@ -51,6 +57,7 @@ static QCString g_header;
static QCString g_footer;
static QCString g_mathjax_code;
+static bool DoxyCodeLineOpen = FALSE;
// note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this
// part will be rendered inside menu.js
@@ -524,7 +531,12 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename,
qsnprintf(lineNumber,maxLineNrStr,"%5d",l);
qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l);
- m_t << "<div class=\"line\">";
+ if (!DoxyCodeLineOpen)
+ {
+ m_t << "<div class=\"line\">";
+ DoxyCodeLineOpen = TRUE;
+ }
+
m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">";
if (filename)
{
@@ -655,12 +667,16 @@ void HtmlCodeGenerator::writeTooltip(const char *id, const DocLinkInfo &docInfo,
}
-void HtmlCodeGenerator::startCodeLine(bool hasLineNumbers)
+void HtmlCodeGenerator::startCodeLine(bool)
{
if (m_streamSet)
{
- if (!hasLineNumbers) m_t << "<div class=\"line\">";
m_col=0;
+ if (!DoxyCodeLineOpen)
+ {
+ m_t << "<div class=\"line\">";
+ DoxyCodeLineOpen = TRUE;
+ }
}
}
@@ -673,7 +689,11 @@ void HtmlCodeGenerator::endCodeLine()
m_t << " ";
m_col++;
}
- m_t << "</div>";
+ if (DoxyCodeLineOpen)
+ {
+ m_t << "</div>\n";
+ DoxyCodeLineOpen = FALSE;
+ }
}
}
@@ -1775,7 +1795,7 @@ void HtmlGenerator::startDotGraph()
startSectionHeader(t,relPath,m_sectionCount);
}
-void HtmlGenerator::endDotGraph(const DotClassGraph &g)
+void HtmlGenerator::endDotGraph(DotClassGraph &g)
{
bool generateLegend = Config_getBool(GENERATE_LEGEND);
bool umlLook = Config_getBool(UML_LOOK);
@@ -1803,7 +1823,7 @@ void HtmlGenerator::startInclDepGraph()
startSectionHeader(t,relPath,m_sectionCount);
}
-void HtmlGenerator::endInclDepGraph(const DotInclDepGraph &g)
+void HtmlGenerator::endInclDepGraph(DotInclDepGraph &g)
{
endSectionHeader(t);
startSectionSummary(t,m_sectionCount);
@@ -1821,7 +1841,7 @@ void HtmlGenerator::startGroupCollaboration()
startSectionHeader(t,relPath,m_sectionCount);
}
-void HtmlGenerator::endGroupCollaboration(const DotGroupCollaboration &g)
+void HtmlGenerator::endGroupCollaboration(DotGroupCollaboration &g)
{
endSectionHeader(t);
startSectionSummary(t,m_sectionCount);
@@ -1839,7 +1859,7 @@ void HtmlGenerator::startCallGraph()
startSectionHeader(t,relPath,m_sectionCount);
}
-void HtmlGenerator::endCallGraph(const DotCallGraph &g)
+void HtmlGenerator::endCallGraph(DotCallGraph &g)
{
endSectionHeader(t);
startSectionSummary(t,m_sectionCount);
@@ -1857,7 +1877,7 @@ void HtmlGenerator::startDirDepGraph()
startSectionHeader(t,relPath,m_sectionCount);
}
-void HtmlGenerator::endDirDepGraph(const DotDirDeps &g)
+void HtmlGenerator::endDirDepGraph(DotDirDeps &g)
{
endSectionHeader(t);
startSectionSummary(t,m_sectionCount);
@@ -1870,7 +1890,7 @@ void HtmlGenerator::endDirDepGraph(const DotDirDeps &g)
m_sectionCount++;
}
-void HtmlGenerator::writeGraphicalHierarchy(const DotGfxHierarchyTable &g)
+void HtmlGenerator::writeGraphicalHierarchy(DotGfxHierarchyTable &g)
{
g.writeGraph(t,dir,fileName);
}
@@ -1994,7 +2014,7 @@ void HtmlGenerator::endParamList()
t << "</dl>";
}
-void HtmlGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
+void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *)
{
HtmlDocVisitor *visitor = new HtmlDocVisitor(t,m_codeGen,ctx);
n->accept(visitor);
@@ -2634,6 +2654,19 @@ void HtmlGenerator::endConstraintList()
t << "</div>" << endl;
}
+void HtmlGenerator::startCodeFragment()
+{
+ t << PREFRAG_START;
+}
+
+void HtmlGenerator::endCodeFragment()
+{
+ //endCodeLine checks is there is still an open code line, if so closes it.
+ endCodeLine();
+
+ t << PREFRAG_END;
+}
+
void HtmlGenerator::lineBreak(const char *style)
{
if (style)
@@ -2819,7 +2852,7 @@ void HtmlGenerator::endMemberDeclaration(const char *anchor,const char *inheritI
t << "\"><td class=\"memSeparator\" colspan=\"2\">&#160;</td></tr>\n";
}
-void HtmlGenerator::setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile)
+void HtmlGenerator::setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile)
{
if (Doxygen::searchIndex)
{
diff --git a/src/htmlgen.h b/src/htmlgen.h
index 221269f..2db5b74 100644
--- a/src/htmlgen.h
+++ b/src/htmlgen.h
@@ -52,7 +52,7 @@ class HtmlCodeGenerator : public CodeOutputInterface
void startFontClass(const char *s);
void endFontClass();
void writeCodeAnchor(const char *anchor);
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
private:
@@ -119,9 +119,9 @@ class HtmlGenerator : public OutputGenerator
{ m_codeGen.writeCodeAnchor(anchor); }
// ---------------------------
- void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile);
+ void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile);
void addWord(const char *word,bool hiPriority);
- void writeDoc(DocNode *,Definition *,MemberDef *);
+ void writeDoc(DocNode *,const Definition *,const MemberDef *);
void startFile(const char *name,const char *manName,const char *title);
void writeFooter(const char *navPath);
@@ -212,8 +212,8 @@ class HtmlGenerator : public OutputGenerator
void writeRuler() { t << "<hr/>"; }
void writeAnchor(const char *,const char *name)
{ t << "<a name=\"" << name <<"\" id=\"" << name << "\"></a>"; }
- void startCodeFragment() { t << PREFRAG_START; }
- void endCodeFragment() { t << PREFRAG_END; }
+ void startCodeFragment();
+ void endCodeFragment();
void startEmphasis() { t << "<em>"; }
void endEmphasis() { t << "</em>"; }
void startBold() { t << "<b>"; }
@@ -283,16 +283,16 @@ class HtmlGenerator : public OutputGenerator
void endDescTableData();
void startDotGraph();
- void endDotGraph(const DotClassGraph &g);
+ void endDotGraph(DotClassGraph &g);
void startInclDepGraph();
- void endInclDepGraph(const DotInclDepGraph &g);
+ void endInclDepGraph(DotInclDepGraph &g);
void startGroupCollaboration();
- void endGroupCollaboration(const DotGroupCollaboration &g);
+ void endGroupCollaboration(DotGroupCollaboration &g);
void startCallGraph();
- void endCallGraph(const DotCallGraph &g);
+ void endCallGraph(DotCallGraph &g);
void startDirDepGraph();
- void endDirDepGraph(const DotDirDeps &g);
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &g);
+ void endDirDepGraph(DotDirDeps &g);
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &g);
void startTextBlock(bool)
{ t << "<div class=\"textblock\">"; }
diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp
index 3ed3d64..20cb6ca 100644
--- a/src/htmlhelp.cpp
+++ b/src/htmlhelp.cpp
@@ -632,7 +632,7 @@ void HtmlHelp::addContentsItem(bool isDir,
const char *anchor,
bool /* separateIndex */,
bool /* addToNavIndex */,
- Definition * /* def */)
+ const Definition * /* def */)
{
// If we're using a binary toc then folders cannot have links.
// Tried this and I didn't see any problems, when not using
@@ -677,7 +677,7 @@ void HtmlHelp::addContentsItem(bool isDir,
}
-void HtmlHelp::addIndexItem(Definition *context,MemberDef *md,
+void HtmlHelp::addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor,const char *word)
{
if (md)
diff --git a/src/htmlhelp.h b/src/htmlhelp.h
index 9c3fa04..184b929 100644
--- a/src/htmlhelp.h
+++ b/src/htmlhelp.h
@@ -78,8 +78,8 @@ class HtmlHelp : public IndexIntf
const char *anchor,
bool separateIndex,
bool addToNavIndex,
- Definition *def);
- void addIndexItem(Definition *context,MemberDef *md,
+ const Definition *def);
+ void addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor, const char *title);
void addIndexFile(const char *name);
void addImageFile(const char *);
diff --git a/src/index.cpp b/src/index.cpp
index b401a0a..5d6c0a5 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -40,6 +40,7 @@
#include "htmlhelp.h"
#include "ftvhelp.h"
#include "dot.h"
+#include "dotgfxhierarchytable.h"
#include "pagedef.h"
#include "dirdef.h"
#include "vhdldocgen.h"
@@ -146,7 +147,7 @@ static void endIndexHierarchy(OutputList &ol,int level)
class MemberIndexList : public QList<MemberDef>
{
public:
- typedef MemberDef ElementType;
+ typedef const MemberDef ElementType;
MemberIndexList(uint letter) : QList<MemberDef>(), m_letter(letter) {}
~MemberIndexList() {}
int compareValues(const MemberDef *md1, const MemberDef *md2) const
@@ -252,7 +253,7 @@ QCString fixSpaces(const QCString &s)
return substitute(s," ","&#160;");
}
-void startTitle(OutputList &ol,const char *fileName,Definition *def)
+void startTitle(OutputList &ol,const char *fileName,const Definition *def)
{
ol.startHeaderSection();
if (def) def->writeSummaryLinks(ol);
@@ -285,7 +286,6 @@ void startFile(OutputList &ol,const char *name,const char *manName,
}
ol.writeSplitBar(altSidebarName ? altSidebarName : name);
ol.writeSearchInfo();
- resetDotNodeNumbering();
}
void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents,
@@ -309,7 +309,7 @@ void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents,
TooltipManager::instance()->clearTooltips(); // Only clear after the last is written
}
-void endFileWithNavPath(Definition *d,OutputList &ol)
+void endFileWithNavPath(const Definition *d,OutputList &ol)
{
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
QCString navPath;
@@ -365,7 +365,7 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part,
MemberDef *md;
for (mi.toFirst();(md=mi.current());++mi)
{
- MemberList *enumList = md->enumFieldList();
+ const MemberList *enumList = md->enumFieldList();
bool isDir = enumList!=0 && md->isEnumerate();
bool isAnonymous = md->name().find('@')!=-1;
static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
@@ -1649,14 +1649,14 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO
}
}
-static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv,
+static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv,
bool rootOnly,bool showClasses,bool addToIndex,ClassDef::CompoundType ct)
{
static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE);
if (nsDict)
{
NamespaceSDict::Iterator nli(*nsDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
if (nd->localName().find('@')==-1 &&
@@ -1985,7 +1985,7 @@ static QCString letterToLabel(uint startLetter)
class PrefixIgnoreClassList : public ClassList
{
public:
- typedef ClassDef ElementType;
+ typedef const ClassDef ElementType;
PrefixIgnoreClassList(uint letter) : m_letter(letter) {}
uint letter() const { return m_letter; }
private:
@@ -2071,7 +2071,7 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct
// first count the number of headers
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
uint startLetter=0;
int headerItems=0;
for (;(cd=cli.current());++cli)
@@ -2748,7 +2748,7 @@ static void writeAnnotatedExceptionIndex(OutputList &ol)
static void writeClassLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
QCString &prevClassName)
{
- ClassDef *cd=md->getClassDef();
+ const ClassDef *cd=md->getClassDef();
if ( cd && prevClassName!=cd->displayName())
{
ol.docify(separator);
@@ -2762,7 +2762,7 @@ static void writeClassLinkForMember(OutputList &ol,MemberDef *md,const char *sep
static void writeFileLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
QCString &prevFileName)
{
- FileDef *fd=md->getFileDef();
+ const FileDef *fd=md->getFileDef();
if (fd && prevFileName!=fd->name())
{
ol.docify(separator);
@@ -2776,7 +2776,7 @@ static void writeFileLinkForMember(OutputList &ol,MemberDef *md,const char *sepa
static void writeNamespaceLinkForMember(OutputList &ol,MemberDef *md,const char *separator,
QCString &prevNamespaceName)
{
- NamespaceDef *nd=md->getNamespaceDef();
+ const NamespaceDef *nd=md->getNamespaceDef();
if (nd && prevNamespaceName!=nd->displayName())
{
ol.docify(separator);
@@ -2898,9 +2898,7 @@ void initClassMemberIndices()
void addClassMemberNameToIndex(MemberDef *md)
{
static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
- ClassDef *cd=0;
-
-
+ const ClassDef *cd=0;
if (md->isLinkableInProject() &&
(cd=md->getClassDef()) &&
@@ -2982,7 +2980,7 @@ void initNamespaceMemberIndices()
void addNamespaceMemberNameToIndex(MemberDef *md)
{
- NamespaceDef *nd=md->getNamespaceDef();
+ const NamespaceDef *nd=md->getNamespaceDef();
if (nd && nd->isLinkableInProject() && md->isLinkableInProject())
{
QCString n = md->name();
@@ -3049,7 +3047,7 @@ void initFileMemberIndices()
void addFileMemberNameToIndex(MemberDef *md)
{
- FileDef *fd=md->getFileDef();
+ const FileDef *fd=md->getFileDef();
if (fd && fd->isLinkableInProject() && md->isLinkableInProject())
{
QCString n = md->name();
@@ -4052,7 +4050,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp*
MemberDef *md;
for (mi.toFirst();(md=mi.current());++mi)
{
- MemberList *enumList = md->enumFieldList();
+ const MemberList *enumList = md->enumFieldList();
bool isDir = enumList!=0 && md->isEnumerate();
if (md->isVisible() && md->name().find('@')==-1)
{
@@ -4733,7 +4731,7 @@ static void writeIndex(OutputList &ol)
ol.parseText(/*projPrefix+*/theTranslator->trExceptionIndex());
ol.endIndexSection(isCompoundIndex);
}
- if (documentedFiles>0)
+ if (Config_getBool(SHOW_FILES) && (documentedFiles>0))
{
ol.startIndexSection(isFileIndex);
ol.parseText(/*projPrefix+*/theTranslator->trFileIndex());
diff --git a/src/index.h b/src/index.h
index f3e0241..c6baba5 100644
--- a/src/index.h
+++ b/src/index.h
@@ -37,8 +37,8 @@ class IndexIntf
virtual void decContentsDepth() = 0;
virtual void addContentsItem(bool isDir, const char *name, const char *ref,
const char *file, const char *anchor, bool separateIndex,
- bool addToNavIndex,Definition *def) = 0;
- virtual void addIndexItem(Definition *context,MemberDef *md,
+ bool addToNavIndex,const Definition *def) = 0;
+ virtual void addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor,const char *title) = 0;
virtual void addIndexFile(const char *name) = 0;
virtual void addImageFile(const char *name) = 0;
@@ -136,11 +136,11 @@ class IndexList : public IndexIntf
{ if (m_enabled) foreach(&IndexIntf::decContentsDepth); }
void addContentsItem(bool isDir, const char *name, const char *ref,
const char *file, const char *anchor,bool separateIndex=FALSE,bool addToNavIndex=FALSE,
- Definition *def=0)
- { if (m_enabled) foreach<bool,const char *,const char *,const char *,const char*,bool,bool,Definition *>
+ const Definition *def=0)
+ { if (m_enabled) foreach<bool,const char *,const char *,const char *,const char*,bool,bool,const Definition *>
(&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); }
- void addIndexItem(Definition *context,MemberDef *md,const char *sectionAnchor=0,const char *title=0)
- { if (m_enabled) foreach<Definition *,MemberDef *,const char *,const char *>
+ void addIndexItem(const Definition *context,const MemberDef *md,const char *sectionAnchor=0,const char *title=0)
+ { if (m_enabled) foreach<const Definition *,const MemberDef *,const char *,const char *>
(&IndexIntf::addIndexItem,context,md,sectionAnchor,title); }
void addIndexFile(const char *name)
{ if (m_enabled) foreach<const char *>(&IndexIntf::addIndexFile,name); }
@@ -289,14 +289,14 @@ extern int documentedDirs;
extern int documentedHtmlFiles;
extern int documentedPages;
-void startTitle(OutputList &ol,const char *fileName,Definition *def=0);
+void startTitle(OutputList &ol,const char *fileName,const Definition *def=0);
void endTitle(OutputList &ol,const char *fileName,const char *name);
void startFile(OutputList &ol,const char *name,const char *manName,
const char *title,HighlightedItem hli=HLI_None,
bool additionalIndices=FALSE,const char *altSidebarName=0);
void endFile(OutputList &ol,bool skipNavIndex=FALSE,bool skipEndContents=FALSE,
const QCString &navPath=QCString());
-void endFileWithNavPath(Definition *d,OutputList &ol);
+void endFileWithNavPath(const Definition *d,OutputList &ol);
void initClassMemberIndices();
void initFileMemberIndices();
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index 2e979bd..9652580 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -566,20 +566,22 @@ void LatexDocVisitor::visit(DocIncOperator *op)
pushEnabled();
m_hide = TRUE;
}
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
if (op->type()!=DocIncOperator::Skip)
{
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(m_ci,op->context(),op->text(),langExt,
op->isExample(),op->exampleFile(),
fd, // fileDef
@@ -1696,14 +1698,6 @@ void LatexDocVisitor::visitPost(DocInternalRef *ref)
endLink(0,ref->file(),ref->anchor());
}
-void LatexDocVisitor::visitPre(DocCopy *)
-{
-}
-
-void LatexDocVisitor::visitPost(DocCopy *)
-{
-}
-
void LatexDocVisitor::visitPre(DocText *)
{
}
diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h
index 7ea8ae1..71fb5be 100644
--- a/src/latexdocvisitor.h
+++ b/src/latexdocvisitor.h
@@ -128,8 +128,6 @@ class LatexDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 36109fe..e6c6861 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -27,6 +27,11 @@
#include "language.h"
#include "version.h"
#include "dot.h"
+#include "dotcallgraph.h"
+#include "dotclassgraph.h"
+#include "dotdirdeps.h"
+#include "dotgroupcollaboration.h"
+#include "dotincldepgraph.h"
#include "pagedef.h"
#include "docparser.h"
#include "latexdocvisitor.h"
@@ -480,7 +485,7 @@ static void writeDefaultHeaderPart1(FTextStream &t)
if (Config_getBool(LATEX_BATCHMODE))
t << "\\batchmode\n";
- // to overcome problems wit too many open files
+ // to overcome problems with too many open files
t << "\\let\\mypdfximage\\pdfximage"
"\\def\\pdfximage{\\immediate\\mypdfximage}";
@@ -492,6 +497,14 @@ static void writeDefaultHeaderPart1(FTextStream &t)
documentClass = "book";
t << "\\documentclass[twoside]{" << documentClass << "}\n"
"\n";
+ t << "%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package\n"
+ "\\usepackage{ifthen}\n"
+ "\\ifx\\requestedLaTeXdate\\undefined\n"
+ "\\usepackage{array}\n"
+ "\\else\n"
+ "\\usepackage{array}[=2016-10-06]\n"
+ "\\fi\n"
+ "%%\n";
// Load required packages
t << "% Packages required by doxygen\n"
@@ -1324,6 +1337,15 @@ void LatexGenerator::writeStyleInfo(int part)
startPlainFile("doxygen.sty");
writeDefaultStyleSheet(t);
endPlainFile();
+
+ // workaround for the problem caused by change in LaTeX in version 2019
+ // in the unmaintained tabu package
+ startPlainFile("tabu_doxygen.sty");
+ t << ResourceMgr::instance().getAsString("tabu_doxygen.sty");
+ endPlainFile();
+ startPlainFile("longtable_doxygen.sty");
+ t << ResourceMgr::instance().getAsString("longtable_doxygen.sty");
+ endPlainFile();
}
void LatexGenerator::newParagraph()
@@ -1376,7 +1398,7 @@ void LatexGenerator::startHtmlLink(const char *url)
if (Config_getBool(PDF_HYPERLINKS))
{
t << "\\href{";
- t << url;
+ t << latexFilterURL(url);
t << "}";
}
t << "{\\texttt{ ";
@@ -2034,7 +2056,7 @@ void LatexGenerator::startDotGraph()
newParagraph();
}
-void LatexGenerator::endDotGraph(const DotClassGraph &g)
+void LatexGenerator::endDotGraph(DotClassGraph &g)
{
g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
}
@@ -2043,7 +2065,7 @@ void LatexGenerator::startInclDepGraph()
{
}
-void LatexGenerator::endInclDepGraph(const DotInclDepGraph &g)
+void LatexGenerator::endInclDepGraph(DotInclDepGraph &g)
{
g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
}
@@ -2052,7 +2074,7 @@ void LatexGenerator::startGroupCollaboration()
{
}
-void LatexGenerator::endGroupCollaboration(const DotGroupCollaboration &g)
+void LatexGenerator::endGroupCollaboration(DotGroupCollaboration &g)
{
g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
}
@@ -2061,7 +2083,7 @@ void LatexGenerator::startCallGraph()
{
}
-void LatexGenerator::endCallGraph(const DotCallGraph &g)
+void LatexGenerator::endCallGraph(DotCallGraph &g)
{
g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
}
@@ -2070,7 +2092,7 @@ void LatexGenerator::startDirDepGraph()
{
}
-void LatexGenerator::endDirDepGraph(const DotDirDeps &g)
+void LatexGenerator::endDirDepGraph(DotDirDeps &g)
{
g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
}
@@ -2175,7 +2197,7 @@ void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket)
t << " ";
}
-void LatexGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
+void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *)
{
LatexDocVisitor *visitor =
new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),insideTabbing);
diff --git a/src/latexgen.h b/src/latexgen.h
index 1460000..6430dbc 100644
--- a/src/latexgen.h
+++ b/src/latexgen.h
@@ -49,7 +49,7 @@ class LatexCodeGenerator : public CodeOutputInterface
void startFontClass(const char *);
void endFontClass();
void writeCodeAnchor(const char *) {}
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
static void setDoxyCodeOpen(bool val);
@@ -116,7 +116,7 @@ class LatexGenerator : public OutputGenerator
// ---------------------------
- void writeDoc(DocNode *,Definition *ctx,MemberDef *);
+ void writeDoc(DocNode *,const Definition *ctx,const MemberDef *);
void startFile(const char *name,const char *manName,const char *title);
void writeSearchInfo() {}
@@ -273,16 +273,16 @@ class LatexGenerator : public OutputGenerator
void lastIndexPage();
void startDotGraph();
- void endDotGraph(const DotClassGraph &);
+ void endDotGraph(DotClassGraph &);
void startInclDepGraph();
- void endInclDepGraph(const DotInclDepGraph &);
+ void endInclDepGraph(DotInclDepGraph &);
void startCallGraph();
void startGroupCollaboration();
- void endGroupCollaboration(const DotGroupCollaboration &g);
- void endCallGraph(const DotCallGraph &);
+ void endGroupCollaboration(DotGroupCollaboration &g);
+ void endCallGraph(DotCallGraph &);
void startDirDepGraph();
- void endDirDepGraph(const DotDirDeps &g);
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {}
+ void endDirDepGraph(DotDirDeps &g);
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
void startTextBlock(bool) {}
void endTextBlock(bool) {}
@@ -321,7 +321,7 @@ class LatexGenerator : public OutputGenerator
void writeLabel(const char *l,bool isLast);
void endLabels();
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
diff --git a/src/layout.cpp b/src/layout.cpp
index f9fe3b0..30c41f9 100644
--- a/src/layout.cpp
+++ b/src/layout.cpp
@@ -106,7 +106,7 @@ QCString LayoutNavEntry::url() const
}
else if (url.left(5)=="@ref " || url.left(5)=="\\ref ")
{
- Definition *d;
+ const Definition *d = 0;
QCString anchor;
bool found=FALSE;
if (resolveLink(0,url.mid(5).stripWhiteSpace(),TRUE,&d,anchor))
@@ -1538,10 +1538,11 @@ void LayoutDocManager::clear(LayoutDocManager::LayoutPart p)
d->docEntries[(int)p].clear();
}
-void LayoutDocManager::parse(QTextStream &t,const char *fileName)
+void LayoutDocManager::parse(const char *fileName)
{
LayoutErrorHandler errorHandler(fileName);
- QXmlInputSource source( t );
+ QXmlInputSource source;
+ source.setData(fileToString(fileName));
QXmlSimpleReader reader;
reader.setContentHandler( &LayoutParser::instance() );
reader.setErrorHandler( &errorHandler );
diff --git a/src/layout.h b/src/layout.h
index b25aa4e..b1facf5 100644
--- a/src/layout.h
+++ b/src/layout.h
@@ -201,7 +201,7 @@ class LayoutDocManager
LayoutNavEntry *rootNavEntry() const;
/** Parses a user provided layout */
- void parse(QTextStream &t,const char *fileName);
+ void parse(const char *fileName);
void init();
private:
void addEntry(LayoutPart p,LayoutDocEntry*e);
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index 5c98c6f..9f5a45b 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -367,7 +367,9 @@ void ManDocVisitor::visit(DocInclude *inc)
void ManDocVisitor::visit(DocIncOperator *op)
{
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
//printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
// op->type(),op->isFirst(),op->isLast(),op->text().data());
if (op->isFirst())
@@ -386,14 +388,14 @@ void ManDocVisitor::visit(DocIncOperator *op)
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(m_ci,op->context(),op->text(),langExt,
op->isExample(),op->exampleFile(),
fd, // fileDef
@@ -569,7 +571,7 @@ void ManDocVisitor::visitPre(DocSimpleSect *s)
// special case 1: user defined title
if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
{
- m_t << ":\\fP" << endl;
+ m_t << "\\fP" << endl;
m_t << ".RS 4" << endl;
}
}
@@ -942,7 +944,7 @@ void ManDocVisitor::visitPre(DocParamSect *s)
default:
ASSERT(0);
}
- m_t << ":\\fP" << endl;
+ m_t << "\\fP" << endl;
m_t << ".RS 4" << endl;
}
@@ -1026,14 +1028,6 @@ void ManDocVisitor::visitPost(DocInternalRef *)
m_t << "\\fP";
}
-void ManDocVisitor::visitPre(DocCopy *)
-{
-}
-
-void ManDocVisitor::visitPost(DocCopy *)
-{
-}
-
void ManDocVisitor::visitPre(DocText *)
{
}
diff --git a/src/mandocvisitor.h b/src/mandocvisitor.h
index 8efc223..fa65424 100644
--- a/src/mandocvisitor.h
+++ b/src/mandocvisitor.h
@@ -128,8 +128,6 @@ class ManDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
diff --git a/src/mangen.cpp b/src/mangen.cpp
index b3ae732..06d3c4a 100644
--- a/src/mangen.cpp
+++ b/src/mangen.cpp
@@ -706,7 +706,7 @@ void ManGenerator::endParamList()
{
}
-void ManGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
+void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *)
{
ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""));
n->accept(visitor);
diff --git a/src/mangen.h b/src/mangen.h
index e109355..d912923 100644
--- a/src/mangen.h
+++ b/src/mangen.h
@@ -41,7 +41,7 @@ class ManGenerator : public OutputGenerator
bool isEnabled(OutputType o) { return (o==Man && active); }
OutputGenerator *get(OutputType o) { return (o==Man) ? this : 0; }
- void writeDoc(DocNode *,Definition *,MemberDef *);
+ void writeDoc(DocNode *,const Definition *,const MemberDef *);
static void init();
void startFile(const char *name,const char *manName,const char *title);
@@ -207,16 +207,16 @@ class ManGenerator : public OutputGenerator
void endDescTableData() {}
void startDotGraph() {}
- void endDotGraph(const DotClassGraph &) {}
+ void endDotGraph(DotClassGraph &) {}
void startInclDepGraph() {}
- void endInclDepGraph(const DotInclDepGraph &) {}
+ void endInclDepGraph(DotInclDepGraph &) {}
void startGroupCollaboration() {}
- void endGroupCollaboration(const DotGroupCollaboration &) {}
+ void endGroupCollaboration(DotGroupCollaboration &) {}
void startCallGraph() {}
- void endCallGraph(const DotCallGraph &) {}
+ void endCallGraph(DotCallGraph &) {}
void startDirDepGraph() {}
- void endDirDepGraph(const DotDirDeps &) {}
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {}
+ void endDirDepGraph(DotDirDeps &) {}
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
void startTextBlock(bool) {}
void endTextBlock(bool) {}
@@ -260,7 +260,7 @@ class ManGenerator : public OutputGenerator
void endLabels();
void writeCodeAnchor(const char *) {}
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
private:
diff --git a/src/markdown.cpp b/src/markdown.cpp
index dea2476..8670642 100644
--- a/src/markdown.cpp
+++ b/src/markdown.cpp
@@ -107,13 +107,7 @@ static action_t g_actions[256];
static Entry *g_current;
static QCString g_fileName;
static int g_lineNr;
-
-// In case a markdown page starts with a level1 header, that header is used
-// as a title of the page, in effect making it a level0 header, so the
-// level of all other sections needs to be corrected as well.
-// This flag is TRUE if corrections are needed.
-//static bool g_correctSectionLevel;
-
+static int g_indentLevel=0; // 0 is outside markdown, -1=page level
//----------
@@ -915,7 +909,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
{
SrcLangExt lang = getLanguageFromFileName(link);
int lp=-1;
- if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || lang==SrcLangExt_Markdown)
+ if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || (lang==SrcLangExt_Markdown && !isURL(link)))
// assume doxygen symbol link
{
if (lp==-1) // link to markdown page
@@ -1103,7 +1097,7 @@ static void processInline(GrowBuf &out,const char *data,int size)
}
/** returns whether the line is a setext-style hdr underline */
-static int isHeaderline(const char *data, int size)
+static int isHeaderline(const char *data, int size, bool allowAdjustLevel)
{
int i=0, c=0;
while (i<size && data[i]==' ') i++;
@@ -1113,14 +1107,24 @@ static int isHeaderline(const char *data, int size)
{
while (i<size && data[i]=='=') i++,c++;
while (i<size && data[i]==' ') i++;
- return (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0;
+ int level = (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0;
+ if (allowAdjustLevel && level==1 && g_indentLevel==-1)
+ {
+ // In case a page starts with a header line we use it as title, promoting it to @page.
+ // We set g_indentLevel to -1 to promoting the other sections if they have a deeper
+ // nesting level than the page header, i.e. @section..@subsection becomes @page..@section.
+ // In case a section at the same level is found (@section..@section) however we need
+ // to undo this (and the result will be @page..@section).
+ g_indentLevel=0;
+ }
+ return g_indentLevel+level;
}
// test of level 2 header
if (data[i]=='-')
{
while (i<size && data[i]=='-') i++,c++;
while (i<size && data[i]==' ') i++;
- return (c>1 && (i>=size || data[i]=='\n')) ? 2 : 0;
+ return (c>1 && (i>=size || data[i]=='\n')) ? g_indentLevel+2 : 0;
}
return 0;
}
@@ -1295,7 +1299,7 @@ static QCString extractTitleId(QCString &title, int level)
static int isAtxHeader(const char *data,int size,
- QCString &header,QCString &id)
+ QCString &header,QCString &id,bool allowAdjustLevel)
{
int i = 0, end;
int level = 0, blanks=0;
@@ -1328,7 +1332,29 @@ static int isAtxHeader(const char *data,int size,
header=header.left(i+1);
}
- return level;
+ if (allowAdjustLevel && level==1 && g_indentLevel==-1)
+ {
+ // in case we find a `# Section` on a markdown page that started with the same level
+ // header, we no longer need to artificially decrease the paragraph level.
+ // So both
+ // -------------------
+ // # heading 1 <-- here we set g_indentLevel to -1
+ // # heading 2 <-- here we set g_indentLevel back to 0 such that this will be a @section
+ // -------------------
+ // and
+ // -------------------
+ // # heading 1 <-- here we set g_indentLevel to -1
+ // ## heading 2 <-- here we keep g_indentLevel at -1 such that @subsection will be @section
+ // -------------------
+ // will convert to
+ // -------------------
+ // @page md_page Heading 1
+ // @section autotoc_md1 Heading 2
+ // -------------------
+
+ g_indentLevel=0;
+ }
+ return level+g_indentLevel;
}
static int isEmptyLine(const char *data,int size)
@@ -1913,10 +1939,8 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size)
{
out.addStr("\n<hr>\n");
}
- else if ((level=isAtxHeader(data,size,header,id)))
+ else if ((level=isAtxHeader(data,size,header,id,TRUE)))
{
- //if (level==1) g_correctSectionLevel=FALSE;
- //if (g_correctSectionLevel) level--;
QCString hTag;
if (level<5 && !id.isEmpty())
{
@@ -2258,10 +2282,8 @@ static QCString processBlocks(const QCString &s,int indent)
QCString lang;
blockIndent = indent;
//printf("isHeaderLine(%s)=%d\n",QCString(data+i).left(size-i).data(),level);
- if ((level=isHeaderline(data+i,size-i))>0)
+ if ((level=isHeaderline(data+i,size-i,TRUE))>0)
{
- //if (level==1) g_correctSectionLevel=FALSE;
- //if (g_correctSectionLevel) level--;
//printf("Found header at %d-%d\n",i,end);
while (pi<size && data[pi]==' ') pi++;
QCString header,id;
@@ -2402,7 +2424,7 @@ static QCString extractPageTitle(QCString &docs,QCString &id)
// second line form end1..end2
int end2=end1+1;
while (end2<size && data[end2-1]!='\n') end2++;
- if (isHeaderline(data+end1,size-end1))
+ if (isHeaderline(data+end1,size-end1,FALSE))
{
convertStringFragment(title,data+i,end1-i-1);
QCString lns;
@@ -2413,10 +2435,14 @@ static QCString extractPageTitle(QCString &docs,QCString &id)
return title;
}
}
- if (i<end1 && isAtxHeader(data+i,end1-i,title,id)>0)
+ if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0)
{
docs=docs.mid(end1);
}
+ else
+ {
+ id = extractTitleId(title, 0);
+ }
//printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
}
@@ -2453,19 +2479,32 @@ static QCString detab(const QCString &s,int &refIndent)
col++;
break;
default: // non-whitespace => update minIndent
- out.addChar(c);
if (c<0 && i<size) // multibyte sequence
{
- out.addChar(data[i++]); // >= 2 bytes
- if (((uchar)c&0xE0)==0xE0 && i<size)
+ // special handling of the UTF-8 nbsp character 0xc2 0xa0
+ if (c == '\xc2' && data[i] == '\xa0')
{
- out.addChar(data[i++]); // 3 bytes
+ out.addStr("&nbsp;");
+ i++;
}
- if (((uchar)c&0xF0)==0xF0 && i<size)
+ else
{
- out.addChar(data[i++]); // 4 byres
+ out.addChar(c);
+ out.addChar(data[i++]); // >= 2 bytes
+ if (((uchar)c&0xE0)==0xE0 && i<size)
+ {
+ out.addChar(data[i++]); // 3 bytes
+ }
+ if (((uchar)c&0xF0)==0xF0 && i<size)
+ {
+ out.addChar(data[i++]); // 4 byres
+ }
}
}
+ else
+ {
+ out.addChar(c);
+ }
if (col<minIndent) minIndent=col;
col++;
}
@@ -2536,6 +2575,7 @@ QCString markdownFileNameToId(const QCString &fileName)
return "md_"+baseName;
}
+
void MarkdownFileParser::parseInput(const char *fileName,
const char *fileBuf,
Entry *root,
@@ -2550,6 +2590,7 @@ void MarkdownFileParser::parseInput(const char *fileName,
QCString docs = fileBuf;
QCString id;
QCString title=extractPageTitle(docs,id).stripWhiteSpace();
+ g_indentLevel=title.isEmpty() ? 0 : -1;
QCString titleFn = QFileInfo(fileName).baseName().utf8();
QCString fn = QFileInfo(fileName).fileName().utf8();
static QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE);
@@ -2616,7 +2657,7 @@ void MarkdownFileParser::parseInput(const char *fileName,
// restore setting
Doxygen::markdownSupport = markdownEnabled;
- //g_correctSectionLevel = FALSE;
+ g_indentLevel=0;
}
void MarkdownFileParser::parseCode(CodeOutputInterface &codeOutIntf,
@@ -2629,9 +2670,9 @@ void MarkdownFileParser::parseCode(CodeOutputInterface &codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
diff --git a/src/markdown.h b/src/markdown.h
index e2e3a74..1a3895e 100644
--- a/src/markdown.h
+++ b/src/markdown.h
@@ -47,9 +47,9 @@ class MarkdownFileParser : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
void resetCodeParserState();
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
index 995901a..4dca53f 100644
--- a/src/memberdef.cpp
+++ b/src/memberdef.cpp
@@ -33,6 +33,7 @@
#include "defargs.h"
#include "docparser.h"
#include "dot.h"
+#include "dotcallgraph.h"
#include "searchindex.h"
#include "parserintf.h"
#include "objcache.h"
@@ -58,6 +59,8 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual ~MemberDefImpl();
virtual DefType definitionType() const { return TypeMember; }
+ virtual MemberDef *resolveAlias() { return this; }
+ virtual const MemberDef *resolveAlias() const { return this; }
virtual MemberDef *deepCopy() const;
virtual void moveTo(Definition *);
virtual QCString getOutputFileBase() const;
@@ -73,15 +76,19 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual const QCString &initializer() const;
virtual int initializerLines() const;
virtual uint64 getMemberSpecifiers() const;
- virtual MemberList *getSectionList(Definition *d) const;
+ virtual const MemberList *getSectionList(const Definition *d) const;
virtual QCString displayDefinition() const;
- virtual ClassDef *getClassDef() const;
- virtual FileDef *getFileDef() const;
- virtual NamespaceDef* getNamespaceDef() const;
+ virtual const ClassDef *getClassDef() const;
+ virtual ClassDef *getClassDef();
+ virtual const FileDef *getFileDef() const;
+ virtual FileDef *getFileDef();
+ virtual const NamespaceDef* getNamespaceDef() const;
+ virtual NamespaceDef* getNamespaceDef();
+ virtual const GroupDef *getGroupDef() const;
+ virtual GroupDef *getGroupDef();
virtual ClassDef *accessorClass() const;
virtual const char *getReadAccessor() const;
virtual const char *getWriteAccessor() const;
- virtual GroupDef *getGroupDef() const;
virtual Grouping::GroupPri_t getGroupPri() const;
virtual const char *getGroupFileName() const;
virtual int getGroupStartLine() const;
@@ -141,7 +148,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual bool isSealed() const;
virtual bool isImplementation() const;
virtual bool isExternal() const;
- virtual bool isAlias() const;
+ virtual bool isTypeAlias() const;
virtual bool isDefault() const;
virtual bool isDelete() const;
virtual bool isNoExcept() const;
@@ -156,8 +163,6 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual bool isMaybeAmbiguous() const;
virtual bool isPublished() const;
virtual bool isTemplateSpecialization() const;
- virtual bool hasDocumentedParams() const;
- virtual bool hasDocumentedReturnType() const;
virtual bool isObjCMethod() const;
virtual bool isObjCProperty() const;
virtual bool isConstructor() const;
@@ -184,22 +189,23 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual bool isDocumentedFriendClass() const;
virtual MemberDef *reimplements() const;
virtual MemberList *reimplementedBy() const;
- virtual bool isReimplementedBy(ClassDef *cd) const;
+ virtual bool isReimplementedBy(const ClassDef *cd) const;
virtual ClassDef *relatedAlso() const;
virtual bool hasDocumentedEnumValues() const;
- virtual MemberDef *getAnonymousEnumType() const;
+ virtual const MemberDef *getAnonymousEnumType() const;
virtual bool isDocsForDefinition() const;
- virtual MemberDef *getEnumScope() const;
- virtual MemberList *enumFieldList() const;
+ virtual const MemberDef *getEnumScope() const;
+ virtual const MemberList *enumFieldList() const;
virtual void setEnumBaseType(const QCString &type);
virtual QCString enumBaseType() const;
- virtual bool hasExamples();
+ virtual bool hasExamples() const;
virtual ExampleSDict *getExamples() const;
virtual bool isPrototype() const;
- virtual ArgumentList *argumentList() const;
- virtual ArgumentList *declArgumentList() const;
- virtual ArgumentList *templateArguments() const;
- virtual QList<ArgumentList> *definitionTemplateParameterLists() const;
+ virtual const ArgumentList *argumentList() const;
+ virtual ArgumentList *argumentList();
+ virtual const ArgumentList *declArgumentList() const;
+ virtual const ArgumentList *templateArguments() const;
+ virtual const QList<ArgumentList> *definitionTemplateParameterLists() const;
virtual int getMemberGroupId() const;
virtual MemberGroup *getMemberGroup() const;
virtual bool fromAnonymousScope() const;
@@ -207,25 +213,25 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual MemberDef *fromAnonymousMember() const;
virtual bool hasCallGraph() const;
virtual bool hasCallerGraph() const;
- virtual bool visibleMemberGroup(bool hideNoHeader);
+ virtual bool visibleMemberGroup(bool hideNoHeader) const;
virtual bool hasReferencesRelation() const;
virtual bool hasReferencedByRelation() const;
virtual MemberDef *templateMaster() const;
virtual QCString getScopeString() const;
- virtual ClassDef *getClassDefOfAnonymousType();
+ virtual ClassDef *getClassDefOfAnonymousType() const;
virtual bool isTypedefValCached() const;
- virtual ClassDef *getCachedTypedefVal() const;
+ virtual const ClassDef *getCachedTypedefVal() const;
virtual QCString getCachedTypedefTemplSpec() const;
virtual QCString getCachedResolvedTypedef() const;
virtual MemberDef *memberDefinition() const;
virtual MemberDef *memberDeclaration() const;
virtual MemberDef *inheritsDocsFrom() const;
- virtual MemberDef *getGroupAlias() const;
+ virtual const MemberDef *getGroupAlias() const;
virtual ClassDef *category() const;
virtual MemberDef *categoryRelation() const;
virtual QCString displayName(bool=TRUE) const;
virtual QCString getDeclType() const;
- virtual void getLabels(QStrList &sl,Definition *container) const;
+ virtual void getLabels(QStrList &sl,const Definition *container) const;
virtual const ArgumentList *typeConstraints() const;
virtual QCString documentation() const;
virtual QCString briefDescription(bool abbr=FALSE) const;
@@ -254,8 +260,6 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual void setTemplateSpecialization(bool b);
virtual void makeRelated();
virtual void makeForeign();
- virtual void setHasDocumentedParams(bool b);
- virtual void setHasDocumentedReturnType(bool b);
virtual void setInheritsDocsFrom(MemberDef *md);
virtual void setTagInfo(TagInfo *i);
virtual void setArgsString(const char *as);
@@ -266,7 +270,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE);
virtual void setEnumClassScope(ClassDef *cd);
virtual void setDocumentedEnumValues(bool value);
- virtual void setAnonymousEnumType(MemberDef *md);
+ virtual void setAnonymousEnumType(const MemberDef *md);
virtual bool addExample(const char *anchor,const char *name,const char *file);
virtual void setPrototype(bool p,const QCString &df,int line, int column);
virtual void setExplicitExternal(bool b,const QCString &df,int line,int column);
@@ -281,7 +285,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual void setMemberGroup(MemberGroup *grp);
virtual void setMemberGroupId(int id);
virtual void makeImplementationDetail();
- virtual void setFromAnonymousScope(bool b);
+ virtual void setFromAnonymousScope(bool b) const;
virtual void setFromAnonymousMember(MemberDef *m);
virtual void enableCallGraph(bool e);
virtual void enableCallerGraph(bool e);
@@ -290,13 +294,13 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual void setTemplateMaster(MemberDef *mt);
virtual void addListReference(Definition *d);
virtual void setDocsForDefinition(bool b);
- virtual void setGroupAlias(MemberDef *md);
- virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType);
+ virtual void setGroupAlias(const MemberDef *md);
+ virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType);
virtual void invalidateTypedefValCache();
virtual void invalidateCachedArgumentTypes();
virtual void setMemberDefinition(MemberDef *md);
virtual void setMemberDeclaration(MemberDef *md);
- virtual void setAnonymousUsed();
+ virtual void setAnonymousUsed() const;
virtual void copyArgumentNames(MemberDef *bmd);
virtual void setCategory(ClassDef *);
virtual void setCategoryRelation(MemberDef *);
@@ -305,42 +309,43 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef
virtual void setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine);
virtual void setHidden(bool b);
virtual void writeDeclaration(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool inGroup, ClassDef *inheritFrom=0,const char *inheritId=0);
- virtual void writeDocumentation(MemberList *ml,int memCount,int memTotal,OutputList &ol,
- const char *scopeName,Definition *container,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const;
+ virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol,
+ const char *scopeName,const Definition *container,
bool inGroup,bool showEnumValues=FALSE,bool
- showInline=FALSE);
- virtual void writeMemberDocSimple(OutputList &ol,Definition *container);
+ showInline=FALSE) const;
+ virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const;
virtual void writeEnumDeclaration(OutputList &typeDecl,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd);
- virtual void writeTagFile(FTextStream &);
- virtual void warnIfUndocumented();
- virtual void warnIfUndocumentedParams();
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const;
+ virtual void writeTagFile(FTextStream &) const;
+ virtual void warnIfUndocumented() const;
+ virtual void warnIfUndocumentedParams() const;
+ virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const;
virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs,
- ArgumentList *actualArgs);
+ ArgumentList *actualArgs) const;
virtual void findSectionsInDocumentation();
virtual void writeLink(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool onlyText=FALSE);
- virtual void addToSearchIndex();
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool onlyText=FALSE) const;
+ virtual void addToSearchIndex() const;
private:
void _computeLinkableInProject();
void _computeIsConstructor();
void _computeIsDestructor();
- void _writeGroupInclude(OutputList &ol,bool inGroup);
- void _writeCallGraph(OutputList &ol);
- void _writeCallerGraph(OutputList &ol);
- void _writeReimplements(OutputList &ol);
- void _writeReimplementedBy(OutputList &ol);
- void _writeExamples(OutputList &ol);
- void _writeTypeConstraints(OutputList &ol);
- void _writeEnumValues(OutputList &ol,Definition *container,
+ void _writeGroupInclude(OutputList &ol,bool inGroup) const;
+ void _writeCallGraph(OutputList &ol) const;
+ void _writeCallerGraph(OutputList &ol) const;
+ void _writeReimplements(OutputList &ol) const;
+ void _writeReimplementedBy(OutputList &ol) const;
+ void _writeExamples(OutputList &ol) const;
+ void _writeTypeConstraints(OutputList &ol) const;
+ void _writeEnumValues(OutputList &ol,const Definition *container,
const QCString &cfname,const QCString &ciname,
- const QCString &cname);
- void _writeCategoryRelation(OutputList &ol);
- void _writeTagData(const DefType);
+ const QCString &cname) const;
+ void _writeCategoryRelation(OutputList &ol) const;
+ void _writeTagData(const DefType) const;
static int s_indentLevel;
@@ -367,6 +372,485 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn,
stat,related,t,tal,al,metaData);
}
+//-----------------------------------------------------------------------------
+
+class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef
+{
+ public:
+ MemberDefAliasImpl(const Definition *newScope,const MemberDef *md)
+ : DefinitionAliasImpl(newScope,md) {}
+ virtual ~MemberDefAliasImpl() {}
+ virtual DefType definitionType() const { return TypeMember; }
+
+ const MemberDef *getMdAlias() const { return dynamic_cast<const MemberDef*>(getAlias()); }
+ virtual MemberDef *resolveAlias() { return const_cast<MemberDef*>(getMdAlias()); }
+ virtual const MemberDef *resolveAlias() const { return getMdAlias(); }
+
+ virtual MemberDef *deepCopy() const {
+ return createMemberDefAlias(getScope(),getMdAlias());
+ }
+ virtual void moveTo(Definition *) {}
+
+ virtual QCString getOutputFileBase() const
+ { return getMdAlias()->getOutputFileBase(); }
+ virtual QCString getReference() const
+ { return getMdAlias()->getReference(); }
+ virtual QCString anchor() const
+ { return getMdAlias()->anchor(); }
+ virtual const char *declaration() const
+ { return getMdAlias()->declaration(); }
+ virtual const char *definition() const
+ { return getMdAlias()->definition(); }
+ virtual const char *typeString() const
+ { return getMdAlias()->typeString(); }
+ virtual const char *argsString() const
+ { return getMdAlias()->argsString(); }
+ virtual const char *excpString() const
+ { return getMdAlias()->excpString(); }
+ virtual const char *bitfieldString() const
+ { return getMdAlias()->bitfieldString(); }
+ virtual const char *extraTypeChars() const
+ { return getMdAlias()->extraTypeChars(); }
+ virtual const QCString &initializer() const
+ { return getMdAlias()->initializer(); }
+ virtual int initializerLines() const
+ { return getMdAlias()->initializerLines(); }
+ virtual uint64 getMemberSpecifiers() const
+ { return getMdAlias()->getMemberSpecifiers(); }
+ virtual const MemberList *getSectionList(const Definition *d) const
+ { return getMdAlias()->getSectionList(d); }
+ virtual QCString displayDefinition() const
+ { return getMdAlias()->displayDefinition(); }
+ virtual const ClassDef *getClassDef() const
+ { return getMdAlias()->getClassDef(); }
+ virtual const FileDef *getFileDef() const
+ { return getMdAlias()->getFileDef(); }
+ virtual const NamespaceDef* getNamespaceDef() const
+ { return getMdAlias()->getNamespaceDef(); }
+ virtual ClassDef *accessorClass() const
+ { return getMdAlias()->accessorClass(); }
+ virtual const char *getReadAccessor() const
+ { return getMdAlias()->getReadAccessor(); }
+ virtual const char *getWriteAccessor() const
+ { return getMdAlias()->getWriteAccessor(); }
+ virtual const GroupDef *getGroupDef() const
+ { return getMdAlias()->getGroupDef(); }
+ virtual Grouping::GroupPri_t getGroupPri() const
+ { return getMdAlias()->getGroupPri(); }
+ virtual const char *getGroupFileName() const
+ { return getMdAlias()->getGroupFileName(); }
+ virtual int getGroupStartLine() const
+ { return getMdAlias()->getGroupStartLine(); }
+ virtual bool getGroupHasDocs() const
+ { return getMdAlias()->getGroupHasDocs(); }
+ virtual QCString qualifiedName() const
+ { return getMdAlias()->qualifiedName(); }
+ virtual QCString objCMethodName(bool localLink,bool showStatic) const
+ { return getMdAlias()->objCMethodName(localLink,showStatic); }
+ virtual Protection protection() const
+ { return getMdAlias()->protection(); }
+ virtual Specifier virtualness(int count) const
+ { return getMdAlias()->virtualness(); }
+ virtual MemberType memberType() const
+ { return getMdAlias()->memberType(); }
+ virtual QCString memberTypeName() const
+ { return getMdAlias()->memberTypeName(); }
+ virtual bool isSignal() const
+ { return getMdAlias()->isSignal(); }
+ virtual bool isSlot() const
+ { return getMdAlias()->isSlot(); }
+ virtual bool isVariable() const
+ { return getMdAlias()->isVariable(); }
+ virtual bool isEnumerate() const
+ { return getMdAlias()->isEnumerate(); }
+ virtual bool isEnumValue() const
+ { return getMdAlias()->isEnumValue(); }
+ virtual bool isTypedef() const
+ { return getMdAlias()->isTypedef(); }
+ virtual bool isSequence() const
+ { return getMdAlias()->isSequence(); }
+ virtual bool isDictionary() const
+ { return getMdAlias()->isDictionary(); }
+ virtual bool isFunction() const
+ { return getMdAlias()->isFunction(); }
+ virtual bool isFunctionPtr() const
+ { return getMdAlias()->isFunctionPtr(); }
+ virtual bool isDefine() const
+ { return getMdAlias()->isDefine(); }
+ virtual bool isFriend() const
+ { return getMdAlias()->isFriend(); }
+ virtual bool isDCOP() const
+ { return getMdAlias()->isDCOP(); }
+ virtual bool isProperty() const
+ { return getMdAlias()->isProperty(); }
+ virtual bool isEvent() const
+ { return getMdAlias()->isEvent(); }
+ virtual bool isRelated() const
+ { return getMdAlias()->isRelated(); }
+ virtual bool isForeign() const
+ { return getMdAlias()->isForeign(); }
+ virtual bool isStatic() const
+ { return getMdAlias()->isStatic(); }
+ virtual bool isInline() const
+ { return getMdAlias()->isInline(); }
+ virtual bool isExplicit() const
+ { return getMdAlias()->isExplicit(); }
+ virtual bool isMutable() const
+ { return getMdAlias()->isMutable(); }
+ virtual bool isGettable() const
+ { return getMdAlias()->isGettable(); }
+ virtual bool isPrivateGettable() const
+ { return getMdAlias()->isPrivateGettable(); }
+ virtual bool isProtectedGettable() const
+ { return getMdAlias()->isProtectedGettable(); }
+ virtual bool isSettable() const
+ { return getMdAlias()->isSettable(); }
+ virtual bool isPrivateSettable() const
+ { return getMdAlias()->isPrivateSettable(); }
+ virtual bool isProtectedSettable() const
+ { return getMdAlias()->isProtectedSettable(); }
+ virtual bool isReadable() const
+ { return getMdAlias()->isReadable(); }
+ virtual bool isWritable() const
+ { return getMdAlias()->isWritable(); }
+ virtual bool isAddable() const
+ { return getMdAlias()->isAddable(); }
+ virtual bool isRemovable() const
+ { return getMdAlias()->isRemovable(); }
+ virtual bool isRaisable() const
+ { return getMdAlias()->isRaisable(); }
+ virtual bool isFinal() const
+ { return getMdAlias()->isFinal(); }
+ virtual bool isAbstract() const
+ { return getMdAlias()->isAbstract(); }
+ virtual bool isOverride() const
+ { return getMdAlias()->isOverride(); }
+ virtual bool isInitonly() const
+ { return getMdAlias()->isInitonly(); }
+ virtual bool isOptional() const
+ { return getMdAlias()->isOptional(); }
+ virtual bool isRequired() const
+ { return getMdAlias()->isRequired(); }
+ virtual bool isNonAtomic() const
+ { return getMdAlias()->isNonAtomic(); }
+ virtual bool isCopy() const
+ { return getMdAlias()->isCopy(); }
+ virtual bool isAssign() const
+ { return getMdAlias()->isAssign(); }
+ virtual bool isRetain() const
+ { return getMdAlias()->isRetain(); }
+ virtual bool isWeak() const
+ { return getMdAlias()->isWeak(); }
+ virtual bool isStrong() const
+ { return getMdAlias()->isStrong(); }
+ virtual bool isUnretained() const
+ { return getMdAlias()->isUnretained(); }
+ virtual bool isNew() const
+ { return getMdAlias()->isNew(); }
+ virtual bool isSealed() const
+ { return getMdAlias()->isSealed(); }
+ virtual bool isImplementation() const
+ { return getMdAlias()->isImplementation(); }
+ virtual bool isExternal() const
+ { return getMdAlias()->isExternal(); }
+ virtual bool isTypeAlias() const
+ { return getMdAlias()->isTypeAlias(); }
+ virtual bool isDefault() const
+ { return getMdAlias()->isDefault(); }
+ virtual bool isDelete() const
+ { return getMdAlias()->isDelete(); }
+ virtual bool isNoExcept() const
+ { return getMdAlias()->isNoExcept(); }
+ virtual bool isAttribute() const
+ { return getMdAlias()->isAttribute(); }
+ virtual bool isUNOProperty() const
+ { return getMdAlias()->isUNOProperty(); }
+ virtual bool isReadonly() const
+ { return getMdAlias()->isReadable(); }
+ virtual bool isBound() const
+ { return getMdAlias()->isBound(); }
+ virtual bool isConstrained() const
+ { return getMdAlias()->isConstrained(); }
+ virtual bool isTransient() const
+ { return getMdAlias()->isTransient(); }
+ virtual bool isMaybeVoid() const
+ { return getMdAlias()->isMaybeVoid(); }
+ virtual bool isMaybeDefault() const
+ { return getMdAlias()->isMaybeDefault(); }
+ virtual bool isMaybeAmbiguous() const
+ { return getMdAlias()->isMaybeAmbiguous(); }
+ virtual bool isPublished() const
+ { return getMdAlias()->isPublished(); }
+ virtual bool isTemplateSpecialization() const
+ { return getMdAlias()->isTemplateSpecialization(); }
+ virtual bool isObjCMethod() const
+ { return getMdAlias()->isObjCMethod(); }
+ virtual bool isObjCProperty() const
+ { return getMdAlias()->isObjCProperty(); }
+ virtual bool isConstructor() const
+ { return getMdAlias()->isConstructor(); }
+ virtual bool isDestructor() const
+ { return getMdAlias()->isDestructor(); }
+ virtual bool hasOneLineInitializer() const
+ { return getMdAlias()->hasOneLineInitializer(); }
+ virtual bool hasMultiLineInitializer() const
+ { return getMdAlias()->hasMultiLineInitializer(); }
+ virtual bool showInCallGraph() const
+ { return getMdAlias()->showInCallGraph(); }
+ virtual bool isStrongEnumValue() const
+ { return getMdAlias()->isStrongEnumValue(); }
+ virtual bool livesInsideEnum() const
+ { return getMdAlias()->livesInsideEnum(); }
+ virtual bool isSliceLocal() const
+ { return getMdAlias()->isSliceLocal(); }
+ virtual bool isConstExpr() const
+ { return getMdAlias()->isConstExpr(); }
+ virtual bool isFriendToHide() const
+ { return getMdAlias()->isFriendToHide(); }
+ virtual bool isNotFriend() const
+ { return getMdAlias()->isNotFriend(); }
+ virtual bool isFunctionOrSignalSlot() const
+ { return getMdAlias()->isFunctionOrSignalSlot(); }
+ virtual bool isRelatedOrFriend() const
+ { return getMdAlias()->isRelatedOrFriend(); }
+ virtual bool isLinkableInProject() const
+ { return getMdAlias()->isLinkableInProject(); }
+ virtual bool isLinkable() const
+ { return getMdAlias()->isLinkable(); }
+ virtual bool hasDocumentation() const
+ { return getMdAlias()->hasDocumentation(); }
+ virtual bool isDeleted() const
+ { return getMdAlias()->isDeleted(); }
+ virtual bool isBriefSectionVisible() const
+ { return getMdAlias()->isBriefSectionVisible(); }
+ virtual bool isDetailedSectionVisible(bool inGroup,bool inFile) const
+ { return getMdAlias()->isDetailedSectionVisible(inGroup,inFile); }
+ virtual bool isDetailedSectionLinkable() const
+ { return getMdAlias()->isDetailedSectionLinkable(); }
+ virtual bool isFriendClass() const
+ { return getMdAlias()->isFriendClass(); }
+ virtual bool isDocumentedFriendClass() const
+ { return getMdAlias()->isDocumentedFriendClass(); }
+ virtual MemberDef *reimplements() const
+ { return getMdAlias()->reimplements(); }
+ virtual MemberList *reimplementedBy() const
+ { return getMdAlias()->reimplementedBy(); }
+ virtual bool isReimplementedBy(const ClassDef *cd) const
+ { return getMdAlias()->isReimplementedBy(cd); }
+ virtual ClassDef *relatedAlso() const
+ { return getMdAlias()->relatedAlso(); }
+ virtual bool hasDocumentedEnumValues() const
+ { return getMdAlias()->hasDocumentedEnumValues(); }
+ virtual const MemberDef *getAnonymousEnumType() const
+ { return getMdAlias()->getAnonymousEnumType(); }
+ virtual bool isDocsForDefinition() const
+ { return getMdAlias()->isDocsForDefinition(); }
+ virtual const MemberDef *getEnumScope() const
+ { return getMdAlias()->getEnumScope(); }
+ virtual const MemberList *enumFieldList() const
+ { return getMdAlias()->enumFieldList(); }
+ virtual QCString enumBaseType() const
+ { return getMdAlias()->enumBaseType(); }
+ virtual bool hasExamples() const
+ { return getMdAlias()->hasExamples(); }
+ virtual ExampleSDict *getExamples() const
+ { return getMdAlias()->getExamples(); }
+ virtual bool isPrototype() const
+ { return getMdAlias()->isPrototype(); }
+ virtual const ArgumentList *argumentList() const
+ { return getMdAlias()->argumentList(); }
+ virtual const ArgumentList *declArgumentList() const
+ { return getMdAlias()->declArgumentList(); }
+ virtual const ArgumentList *templateArguments() const
+ { return getMdAlias()->templateArguments(); }
+ virtual const QList<ArgumentList> *definitionTemplateParameterLists() const
+ { return getMdAlias()->definitionTemplateParameterLists(); }
+ virtual int getMemberGroupId() const
+ { return getMdAlias()->getMemberGroupId(); }
+ virtual MemberGroup *getMemberGroup() const
+ { return getMdAlias()->getMemberGroup(); }
+ virtual bool fromAnonymousScope() const
+ { return getMdAlias()->fromAnonymousScope(); }
+ virtual bool anonymousDeclShown() const
+ { return getMdAlias()->anonymousDeclShown(); }
+ virtual MemberDef *fromAnonymousMember() const
+ { return getMdAlias()->fromAnonymousMember(); }
+ virtual bool hasCallGraph() const
+ { return getMdAlias()->hasCallGraph(); }
+ virtual bool hasCallerGraph() const
+ { return getMdAlias()->hasCallerGraph(); }
+ virtual bool visibleMemberGroup(bool hideNoHeader) const
+ { return getMdAlias()->visibleMemberGroup(hideNoHeader); }
+ virtual bool hasReferencesRelation() const
+ { return getMdAlias()->hasReferencesRelation(); }
+ virtual bool hasReferencedByRelation() const
+ { return getMdAlias()->hasReferencedByRelation(); }
+ virtual MemberDef *templateMaster() const
+ { return getMdAlias()->templateMaster(); }
+ virtual QCString getScopeString() const
+ { return getMdAlias()->getScopeString(); }
+ virtual ClassDef *getClassDefOfAnonymousType() const
+ { return getMdAlias()->getClassDefOfAnonymousType(); }
+ virtual bool isTypedefValCached() const
+ { return getMdAlias()->isTypedefValCached(); }
+ virtual const ClassDef *getCachedTypedefVal() const
+ { return getMdAlias()->getCachedTypedefVal(); }
+ virtual QCString getCachedTypedefTemplSpec() const
+ { return getMdAlias()->getCachedTypedefTemplSpec(); }
+ virtual QCString getCachedResolvedTypedef() const
+ { return getMdAlias()->getCachedResolvedTypedef(); }
+ virtual MemberDef *memberDefinition() const
+ { return getMdAlias()->memberDefinition(); }
+ virtual MemberDef *memberDeclaration() const
+ { return getMdAlias()->memberDeclaration(); }
+ virtual MemberDef *inheritsDocsFrom() const
+ { return getMdAlias()->inheritsDocsFrom(); }
+ virtual const MemberDef *getGroupAlias() const
+ { return getMdAlias()->getGroupAlias(); }
+ virtual ClassDef *category() const
+ { return getMdAlias()->category(); }
+ virtual MemberDef *categoryRelation() const
+ { return getMdAlias()->categoryRelation(); }
+ virtual QCString displayName(bool b=TRUE) const
+ { return getMdAlias()->displayName(b); }
+ virtual QCString getDeclType() const
+ { return getMdAlias()->getDeclType(); }
+ virtual void getLabels(QStrList &sl,const Definition *container) const
+ { return getMdAlias()->getLabels(sl,container); }
+ virtual const ArgumentList *typeConstraints() const
+ { return getMdAlias()->typeConstraints(); }
+ virtual QCString documentation() const
+ { return getMdAlias()->documentation(); }
+ virtual QCString briefDescription(bool abbr=FALSE) const
+ { return getMdAlias()->briefDescription(); }
+ virtual QCString fieldType() const
+ { return getMdAlias()->fieldType(); }
+ virtual bool isReference() const
+ { return getMdAlias()->isReference(); }
+ virtual QCString getDeclFileName() const
+ { return getMdAlias()->getDeclFileName(); }
+ virtual int getDeclLine() const
+ { return getMdAlias()->getDeclLine(); }
+ virtual int getDeclColumn() const
+ { return getMdAlias()->getDeclColumn(); }
+
+ // non-const getters should not be called
+ virtual ClassDef *getClassDef()
+ { err("non-const getClassDef() called on aliased member. Please report as a bug.\n"); return 0; }
+ virtual FileDef *getFileDef()
+ { err("non-const getFileDef() called on aliased member. Please report as a bug.\n"); return 0; }
+ virtual NamespaceDef* getNamespaceDef()
+ { err("non-const getNamespaceDef() called on aliased member. Please report as a bug.\n"); return 0; }
+ virtual GroupDef *getGroupDef()
+ { err("non-const getGroupDef() called on aliased member. Please report as a bug.\n"); return 0; }
+ virtual ArgumentList *argumentList()
+ { err("non-const argumentList() called on aliased member. Please report as bug.\n"); return 0; }
+
+ virtual void setEnumBaseType(const QCString &type) {}
+ virtual void setMemberType(MemberType t) {}
+ virtual void setDefinition(const char *d) {}
+ virtual void setFileDef(FileDef *fd) {}
+ virtual void setAnchor() {}
+ virtual void setProtection(Protection p) {}
+ virtual void setMemberSpecifiers(uint64 s) {}
+ virtual void mergeMemberSpecifiers(uint64 s) {}
+ virtual void setInitializer(const char *i) {}
+ virtual void setBitfields(const char *s) {}
+ virtual void setMaxInitLines(int lines) {}
+ virtual void setMemberClass(ClassDef *cd) {}
+ virtual void setSectionList(Definition *d,MemberList *sl) {}
+ virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri,
+ const QCString &fileName,int startLine,bool hasDocs,
+ MemberDef *member=0) {}
+ virtual void setReadAccessor(const char *r) {}
+ virtual void setWriteAccessor(const char *w) {}
+ virtual void setTemplateSpecialization(bool b) {}
+ virtual void makeRelated() {}
+ virtual void makeForeign() {}
+ virtual void setInheritsDocsFrom(MemberDef *md) {}
+ virtual void setTagInfo(TagInfo *i) {}
+ virtual void setArgsString(const char *as) {}
+ virtual void setReimplements(MemberDef *md) {}
+ virtual void insertReimplementedBy(MemberDef *md) {}
+ virtual void setRelatedAlso(ClassDef *cd) {}
+ virtual void insertEnumField(MemberDef *md) {}
+ virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE) {}
+ virtual void setEnumClassScope(ClassDef *cd) {}
+ virtual void setDocumentedEnumValues(bool value) {}
+ virtual void setAnonymousEnumType(const MemberDef *md) {}
+ virtual bool addExample(const char *anchor,const char *name,const char *file) { return FALSE; }
+ virtual void setPrototype(bool p,const QCString &df,int line, int column) {}
+ virtual void setExplicitExternal(bool b,const QCString &df,int line,int column) {}
+ virtual void setDeclFile(const QCString &df,int line,int column) {}
+ virtual void setArgumentList(ArgumentList *al) {}
+ virtual void setDeclArgumentList(ArgumentList *al) {}
+ virtual void setDefinitionTemplateParameterLists(QList<ArgumentList> *lists) {}
+ virtual void setTypeConstraints(ArgumentList *al) {}
+ virtual void setType(const char *t) {}
+ virtual void setAccessorType(ClassDef *cd,const char *t) {}
+ virtual void setNamespace(NamespaceDef *nd) {}
+ virtual void setMemberGroup(MemberGroup *grp) {}
+ virtual void setMemberGroupId(int id) {}
+ virtual void makeImplementationDetail() {}
+ virtual void setFromAnonymousScope(bool b) const {}
+ virtual void setFromAnonymousMember(MemberDef *m) {}
+ virtual void enableCallGraph(bool e) {}
+ virtual void enableCallerGraph(bool e) {}
+ virtual void enableReferencedByRelation(bool e) {}
+ virtual void enableReferencesRelation(bool e) {}
+ virtual void setTemplateMaster(MemberDef *mt) {}
+ virtual void addListReference(Definition *d) {}
+ virtual void setDocsForDefinition(bool b) {}
+ virtual void setGroupAlias(const MemberDef *md) {}
+ virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) {}
+ virtual void invalidateTypedefValCache() {}
+ virtual void invalidateCachedArgumentTypes() {}
+ virtual void setMemberDefinition(MemberDef *md) {}
+ virtual void setMemberDeclaration(MemberDef *md) {}
+ virtual void setAnonymousUsed() const {}
+ virtual void copyArgumentNames(MemberDef *bmd) {}
+ virtual void setCategory(ClassDef *) {}
+ virtual void setCategoryRelation(MemberDef *) {}
+ virtual void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) {}
+ virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine) {}
+ virtual void setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine) {}
+ virtual void setHidden(bool b) {}
+ virtual void addToSearchIndex() const {}
+ virtual void findSectionsInDocumentation() {}
+ virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs,
+ ArgumentList *actualArgs) const
+ { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); }
+
+ virtual void writeDeclaration(OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const
+ {
+ getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritFrom,inheritId);
+ }
+ virtual void writeEnumDeclaration(OutputList &typeDecl,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const
+ {
+ getMdAlias()->writeEnumDeclaration(typeDecl,cd,nd,fd,gd);
+ }
+ virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol,
+ const char *scopeName,const Definition *container,
+ bool inGroup,bool showEnumValues=FALSE,bool
+ showInline=FALSE) const {}
+ virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const {}
+ virtual void writeLink(OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool onlyText=FALSE) const {}
+ virtual void writeTagFile(FTextStream &) const {}
+ virtual void warnIfUndocumented() const {}
+ virtual void warnIfUndocumentedParams() const {}
+ virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {}
+};
+
+
+MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd)
+{
+ return new MemberDefAliasImpl(newScope,aliasMd);
+}
//-----------------------------------------------------------------------------
@@ -441,9 +925,9 @@ static QCString addTemplateNames(const QCString &s,const QCString &n,const QCStr
// ol.endMemberDoc(hasArgs=FALSE);
//
-static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md)
+static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const MemberDef *md)
{
- ArgumentList *defArgList=(md->isDocsForDefinition()) ?
+ const ArgumentList *defArgList=(md->isDocsForDefinition()) ?
md->argumentList() : md->declArgumentList();
//printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition());
if (defArgList==0 || md->isProperty())
@@ -517,9 +1001,9 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md)
cName=cName.mid(il,ir-il+1);
//printf("1. cName=%s\n",cName.data());
}
- else if (scope->definitionType()==Definition::TypeClass && (dynamic_cast<ClassDef*>(scope))->templateArguments())
+ else if (scope->definitionType()==Definition::TypeClass && (dynamic_cast<const ClassDef*>(scope))->templateArguments())
{
- cName=tempArgListToString((dynamic_cast<ClassDef*>(scope))->templateArguments(),scope->getLanguage());
+ cName=tempArgListToString((dynamic_cast<const ClassDef*>(scope))->templateArguments(),scope->getLanguage());
//printf("2. cName=%s\n",cName.data());
}
else // no template specifier
@@ -712,7 +1196,7 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md)
}
static void writeExceptionListImpl(
- OutputList &ol, ClassDef *cd, MemberDef *md, QCString const& exception)
+ OutputList &ol, const ClassDef *cd, const MemberDef *md, QCString const& exception)
{
// this is ordinary exception spec - there must be a '('
//printf("exception='%s'\n",exception.data());
@@ -750,7 +1234,7 @@ static void writeExceptionListImpl(
}
}
-static void writeExceptionList(OutputList &ol, ClassDef *cd, MemberDef *md)
+static void writeExceptionList(OutputList &ol, const ClassDef *cd, const MemberDef *md)
{
QCString exception(QCString(md->excpString()).stripWhiteSpace());
if ('{'==exception.at(0))
@@ -773,7 +1257,7 @@ static void writeExceptionList(OutputList &ol, ClassDef *cd, MemberDef *md)
}
}
-static void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
+static void writeTemplatePrefix(OutputList &ol,const ArgumentList *al)
{
ol.docify("template<");
ArgumentListIterator ali(*al);
@@ -816,7 +1300,7 @@ class MemberDefImpl::IMPL
MemberDef *enumScope; // the enclosing scope, if this is an enum field
bool livesInsideEnum;
- MemberDef *annEnumType; // the anonymous enum that is the type of this member
+ const MemberDef *annEnumType; // the anonymous enum that is the type of this member
MemberList *enumFields; // enumeration fields
MemberDef *redefines; // the members that this member redefines
@@ -870,7 +1354,7 @@ class MemberDefImpl::IMPL
// cached here.
SDict<MemberList> *classSectionSDict; // not accessible
- MemberDef *groupAlias; // Member containing the definition
+ const MemberDef *groupAlias; // Member containing the definition
int grpId; // group id
MemberGroup *memberGroup; // group's member definition
GroupDef *group; // group in which this member is in
@@ -880,7 +1364,7 @@ class MemberDefImpl::IMPL
MemberDef *groupMember;
bool isTypedefValCached;
- ClassDef *cachedTypedefValue;
+ const ClassDef *cachedTypedefValue;
QCString cachedTypedefTemplSpec;
QCString cachedResolvedType;
@@ -898,15 +1382,17 @@ class MemberDefImpl::IMPL
// objective-c
bool implOnly; // function found in implementation but not
// in the interface
- bool hasDocumentedParams;
- bool hasDocumentedReturnType;
+ mutable bool hasDocumentedParams;
+ mutable bool hasDocumentedReturnType;
bool isDMember;
Relationship related; // relationship of this to the class
bool stat; // is it a static function?
bool proto; // is it a prototype;
bool docEnumValues; // is an enum with documented enum values.
- bool annScope; // member is part of an anonymous scope
- bool annUsed;
+
+ mutable bool annScope; // member is part of an anonymous scope
+ mutable bool annUsed; // ugly: needs to be mutable to allow setAnonymousUsed to act as a
+ // const member.
bool hasCallGraph;
bool hasCallerGraph;
bool hasReferencedByRelation;
@@ -1238,7 +1724,7 @@ MemberList *MemberDefImpl::reimplementedBy() const
return m_impl->redefinedBy;
}
-bool MemberDefImpl::isReimplementedBy(ClassDef *cd) const
+bool MemberDefImpl::isReimplementedBy(const ClassDef *cd) const
{
if (cd && m_impl->redefinedBy)
{
@@ -1246,7 +1732,7 @@ bool MemberDefImpl::isReimplementedBy(ClassDef *cd) const
MemberDef *md;
for (mi.toFirst();(md=mi.current());++mi)
{
- ClassDef *mcd = md->getClassDef();
+ const ClassDef *mcd = md->getClassDef();
if (mcd)
{
if (cd==mcd || cd->isBaseClass(mcd,TRUE))
@@ -1283,7 +1769,7 @@ bool MemberDefImpl::addExample(const char *anchor,const char *nameStr,
return FALSE;
}
-bool MemberDefImpl::hasExamples()
+bool MemberDefImpl::hasExamples() const
{
if (m_impl->exampleSDict==0)
return FALSE;
@@ -1300,33 +1786,37 @@ QCString MemberDefImpl::getOutputFileBase() const
//printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
// name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef,
// m_impl->nspace,m_impl->fileDef);
+ const NamespaceDef *nspace = getNamespaceDef();
+ const FileDef *fileDef = getFileDef();
+ const ClassDef *classDef = getClassDef();
+ const GroupDef *groupDef = getGroupDef();
if (!m_impl->explicitOutputFileBase.isEmpty())
{
return m_impl->explicitOutputFileBase;
}
- else if (m_impl->templateMaster)
+ else if (templateMaster())
{
- return m_impl->templateMaster->getOutputFileBase();
+ return templateMaster()->getOutputFileBase();
}
- else if (m_impl->group)
+ else if (groupDef)
{
- baseName=m_impl->group->getOutputFileBase();
+ baseName=groupDef->getOutputFileBase();
}
- else if (m_impl->classDef)
+ else if (classDef)
{
- baseName=m_impl->classDef->getOutputFileBase();
- if (inlineSimpleClasses && m_impl->classDef->isSimple())
+ baseName=classDef->getOutputFileBase();
+ if (inlineSimpleClasses && classDef->isSimple())
{
return baseName;
}
}
- else if (m_impl->nspace && m_impl->nspace->isLinkableInProject())
+ else if (nspace && nspace->isLinkableInProject())
{
- baseName=m_impl->nspace->getOutputFileBase();
+ baseName=nspace->getOutputFileBase();
}
- else if (m_impl->fileDef)
+ else if (fileDef)
{
- baseName=m_impl->fileDef->getOutputFileBase();
+ baseName=fileDef->getOutputFileBase();
}
if (baseName.isEmpty())
@@ -1358,25 +1848,29 @@ QCString MemberDefImpl::getReference() const
{
return ref;
}
- if (m_impl->templateMaster)
+ const NamespaceDef *nspace = getNamespaceDef();
+ const FileDef *fileDef = getFileDef();
+ const ClassDef *classDef = getClassDef();
+ const GroupDef *groupDef = getGroupDef();
+ if (templateMaster())
{
- return m_impl->templateMaster->getReference();
+ return templateMaster()->getReference();
}
- else if (m_impl->group)
+ else if (groupDef)
{
- return m_impl->group->getReference();
+ return groupDef->getReference();
}
- else if (m_impl->classDef)
+ else if (classDef)
{
- return m_impl->classDef->getReference();
+ return classDef->getReference();
}
- else if (m_impl->nspace)
+ else if (nspace)
{
- return m_impl->nspace->getReference();
+ return nspace->getReference();
}
- else if (m_impl->fileDef)
+ else if (fileDef)
{
- return m_impl->fileDef->getReference();
+ return fileDef->getReference();
}
return "";
}
@@ -1390,7 +1884,7 @@ QCString MemberDefImpl::anchor() const
{
result.prepend(m_impl->enumScope->anchor());
}
- if (m_impl->group)
+ if (getGroupDef())
{
if (m_impl->groupMember)
{
@@ -1416,10 +1910,10 @@ void MemberDefImpl::_computeLinkableInProject()
m_isLinkableCached = 1;
return;
}
- if (m_impl->templateMaster)
+ if (templateMaster())
{
//printf("has template master\n");
- m_isLinkableCached = m_impl->templateMaster->isLinkableInProject() ? 2 : 1;
+ m_isLinkableCached = templateMaster()->isLinkableInProject() ? 2 : 1;
return;
}
if (name().isEmpty() || name().at(0)=='@')
@@ -1434,28 +1928,32 @@ void MemberDefImpl::_computeLinkableInProject()
m_isLinkableCached = 1; // no documentation
return;
}
- if (m_impl->group && !m_impl->group->isLinkableInProject())
+ const GroupDef *groupDef = getGroupDef();
+ const ClassDef *classDef = getClassDef();
+ if (groupDef && !groupDef->isLinkableInProject())
{
//printf("group but group not linkable!\n");
m_isLinkableCached = 1; // group but group not linkable
return;
}
- if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject())
+ if (!groupDef && classDef && !classDef->isLinkableInProject())
{
//printf("in a class but class not linkable!\n");
m_isLinkableCached = 1; // in class but class not linkable
return;
}
- if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject()
- && (m_impl->fileDef==0 || !m_impl->fileDef->isLinkableInProject()))
+ const NamespaceDef *nspace = getNamespaceDef();
+ const FileDef *fileDef = getFileDef();
+ if (!groupDef && nspace && !m_impl->related && !nspace->isLinkableInProject()
+ && (fileDef==0 || !fileDef->isLinkableInProject()))
{
//printf("in a namespace but namespace not linkable!\n");
m_isLinkableCached = 1; // in namespace but namespace not linkable
return;
}
- if (!m_impl->group && !m_impl->nspace &&
- !m_impl->related && !m_impl->classDef &&
- m_impl->fileDef && !m_impl->fileDef->isLinkableInProject())
+ if (!groupDef && !nspace &&
+ !m_impl->related && !classDef &&
+ fileDef && !fileDef->isLinkableInProject())
{
//printf("in a file but file not linkable!\n");
m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable
@@ -1468,7 +1966,7 @@ void MemberDefImpl::_computeLinkableInProject()
m_isLinkableCached = 1; // hidden due to protection
return;
}
- if (m_impl->stat && m_impl->classDef==0 && !extractStatic)
+ if (m_impl->stat && classDef==0 && !extractStatic)
{
//printf("static and invisible!\n");
m_isLinkableCached = 1; // hidden due to staticness
@@ -1535,26 +2033,29 @@ void MemberDefImpl::setDefinitionTemplateParameterLists(QList<ArgumentList> *lis
}
}
-void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
- FileDef *fd,GroupDef *gd,bool onlyText)
+void MemberDefImpl::writeLink(OutputList &ol,
+ const ClassDef *,const NamespaceDef *,const FileDef *fd,const GroupDef *gd,
+ bool onlyText) const
{
SrcLangExt lang = getLanguage();
static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES);
QCString sep = getLanguageSpecificSeparator(lang,TRUE);
QCString n = name();
+ const ClassDef *classDef = getClassDef();
+ const NamespaceDef *nspace = getNamespaceDef();
if (!hideScopeNames)
{
if (m_impl->enumScope && m_impl->livesInsideEnum)
{
n.prepend(m_impl->enumScope->displayName()+sep);
}
- if (m_impl->classDef && gd && !isRelated())
+ if (classDef && gd && !isRelated())
{
- n.prepend(m_impl->classDef->displayName()+sep);
+ n.prepend(classDef->displayName()+sep);
}
- else if (m_impl->nspace && (gd || fd))
+ else if (nspace && (gd || fd))
{
- n.prepend(m_impl->nspace->displayName()+sep);
+ n.prepend(nspace->displayName()+sep);
}
}
@@ -1567,7 +2068,7 @@ void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
if (m_impl->mtype==MemberType_EnumValue && getGroupDef()==0 && // enum value is not grouped
getEnumScope() && getEnumScope()->getGroupDef()) // but its container is
{
- GroupDef *enumValGroup = getEnumScope()->getGroupDef();
+ const GroupDef *enumValGroup = getEnumScope()->getGroupDef();
ol.writeObjectLink(enumValGroup->getReference(),
enumValGroup->getOutputFileBase(),
anchor(),n);
@@ -1588,18 +2089,18 @@ void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
/*! If this member has an anonymous class/struct/union as its type, then
* this method will return the ClassDef that describes this return type.
*/
-ClassDef *MemberDefImpl::getClassDefOfAnonymousType()
+ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const
{
if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
QCString cname;
if (getClassDef()!=0)
{
- cname=getClassDef()->name().copy();
+ cname=getClassDef()->name();
}
else if (getNamespaceDef()!=0)
{
- cname=getNamespaceDef()->name().copy();
+ cname=getNamespaceDef()->name();
}
QCString ltype(m_impl->type);
// strip `static' keyword from ltype
@@ -1746,7 +2247,7 @@ QCString MemberDefImpl::getDeclType() const
{
ltype.prepend("typedef ");
}
- if (isAlias())
+ if (isTypeAlias())
{
ltype="using";
}
@@ -1768,8 +2269,8 @@ QCString MemberDefImpl::getDeclType() const
}
void MemberDefImpl::writeDeclaration(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool inGroup, ClassDef *inheritedFrom,const char *inheritId)
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool inGroup, const ClassDef *inheritedFrom,const char *inheritId) const
{
//printf("%s MemberDefImpl::writeDeclaration() inGroup=%d\n",qualifiedName().data(),inGroup);
@@ -1778,7 +2279,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
if (!inGroup && m_impl->mtype==MemberType_EnumValue) return;
- Definition *d=0;
+ const Definition *d=0;
ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something
if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
if (d==gd) // see bug 753608
@@ -1788,7 +2289,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
else if (getFileDef()) d = getFileDef();
}
- //_writeTagData(compoundType);
addToSearchIndex();
QCString cname = d->name();
@@ -1810,7 +2310,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
// If there is no detailed description we need to write the anchor here.
bool detailsVisible = isDetailedSectionLinkable();
- bool writeAnchor = (inGroup || m_impl->group==0) && // only write anchors for member that have no details and are
+ bool writeAnchor = (inGroup || getGroupDef()==0) && // only write anchors for member that have no details and are
!detailsVisible && !m_impl->annMemb; // rendered inside the group page or are not grouped at all
if (writeAnchor)
{
@@ -1856,7 +2356,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
{
ltype.prepend("typedef ");
}
- if (isAlias())
+ if (isTypeAlias())
{
ltype="using";
}
@@ -1911,7 +2411,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
);
getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd);
//ol+=*getAnonymousEnumType()->enumDecl();
- linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,this,ltype.right(ltype.length()-i-l),TRUE);
+ linkifyText(TextGeneratorOLImpl(ol),d,getFileDef(),this,ltype.right(ltype.length()-i-l),TRUE);
}
else
{
@@ -1978,7 +2478,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
if (!(name().isEmpty() || name().at(0)=='@') && // name valid
(hasDocumentation() || isReference()) && // has docs
!(m_impl->prot==Private && !extractPrivate && (m_impl->virt==Normal || !extractPrivateVirtual) && m_impl->mtype!=MemberType_Friend) && // hidden due to protection
- !(isStatic() && m_impl->classDef==0 && !extractStatic) // hidden due to static-ness
+ !(isStatic() && getClassDef()==0 && !extractStatic) // hidden due to static-ness
)
{
if (m_impl->annMemb)
@@ -1996,8 +2496,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
else
{
//printf("writeLink %s->%d\n",name.data(),hasDocumentation());
- ClassDef *rcd = cd;
- if (isReference() && m_impl->classDef) rcd = m_impl->classDef;
+ const ClassDef *rcd = cd;
+ if (isReference() && getClassDef()) rcd = getClassDef();
writeLink(ol,rcd,nd,fd,gd);
}
}
@@ -2016,8 +2516,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
m_impl->annMemb->setAnonymousUsed();
setAnonymousUsed();
}
- ClassDef *rcd = cd;
- if (isReference() && m_impl->classDef) rcd = m_impl->classDef;
+ const ClassDef *rcd = cd;
+ if (isReference() && getClassDef()) rcd = getClassDef();
writeLink(ol,rcd,nd,fd,gd,TRUE);
}
}
@@ -2090,7 +2590,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer);
}
}
- else if (isAlias()) // using template alias
+ else if (isTypeAlias()) // using template alias
{
ol.writeString(" = ");
linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->type);
@@ -2189,18 +2689,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol,
ol.disableAllBut(OutputGenerator::Html);
//ol.endEmphasis();
ol.docify(" ");
- if (inheritedFrom ||
- separateMemberPages ||
- (m_impl->group!=0 && gd==0) ||
- (m_impl->nspace!=0 && nd==0)
- ) // forward link to the page or group or namespace
- {
- ol.startTextLink(getOutputFileBase(),anchor());
- }
- else // local link
- {
- ol.startTextLink(0,anchor());
- }
+ ol.startTextLink(getOutputFileBase(),anchor());
ol.parseText(theTranslator->trMore());
ol.endTextLink();
//ol.startEmphasis();
@@ -2271,11 +2760,6 @@ bool MemberDefImpl::isDetailedSectionLinkable() const
bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend ||
(m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual);
- // member is part of an anonymous scope that is the type of
- // another member in the list.
- //
- //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed;
-
// hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS
// is true
bool friendCompoundFilter = !(Config_getBool(HIDE_FRIEND_COMPOUNDS) &&
@@ -2287,8 +2771,7 @@ bool MemberDefImpl::isDetailedSectionLinkable() const
);
- bool result = ((docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden()));
- //printf("%s::isDetailedSectionLinkable: %d\n",name().data(),result);
+ bool result = (docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden());
return result;
}
@@ -2310,7 +2793,7 @@ bool MemberDefImpl::isDetailedSectionVisible(bool inGroup,bool inFile) const
return result;
}
-void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const
+void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const
{
static bool inlineInfo = Config_getBool(INLINE_INFO);
@@ -2321,7 +2804,7 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const
(isInline() && inlineInfo) ||
isSignal() || isSlot() ||
isStatic() ||
- (m_impl->classDef && m_impl->classDef!=container && container->definitionType()==TypeClass) ||
+ (getClassDef() && getClassDef()!=container && container->definitionType()==TypeClass) ||
(m_impl->memSpec & ~Entry::Inline)!=0
)
)
@@ -2412,9 +2895,9 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const
sl.append("implementation");
}
}
- if (m_impl->classDef &&
+ if (getClassDef() &&
container->definitionType()==TypeClass &&
- m_impl->classDef!=container &&
+ getClassDef()!=container &&
!isRelated()
)
{
@@ -2428,7 +2911,7 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const
}
}
-void MemberDefImpl::_writeCallGraph(OutputList &ol)
+void MemberDefImpl::_writeCallGraph(OutputList &ol) const
{
// write call graph
if (m_impl->hasCallGraph
@@ -2452,7 +2935,7 @@ void MemberDefImpl::_writeCallGraph(OutputList &ol)
}
}
-void MemberDefImpl::_writeCallerGraph(OutputList &ol)
+void MemberDefImpl::_writeCallerGraph(OutputList &ol) const
{
if (m_impl->hasCallerGraph
&& (isFunction() || isSlot() || isSignal()) && Config_getBool(HAVE_DOT)
@@ -2463,7 +2946,7 @@ void MemberDefImpl::_writeCallerGraph(OutputList &ol)
{
warn_uncond("Caller graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName()));
}
- else if (!callerGraph.isTrivial() && !callerGraph.isTooBig())
+ else if (!callerGraph.isTrivial())
{
msg("Generating caller graph for function %s\n",qPrint(qualifiedName()));
ol.disable(OutputGenerator::Man);
@@ -2475,10 +2958,10 @@ void MemberDefImpl::_writeCallerGraph(OutputList &ol)
}
}
-void MemberDefImpl::_writeReimplements(OutputList &ol)
+void MemberDefImpl::_writeReimplements(OutputList &ol) const
{
MemberDef *bmd=reimplements();
- ClassDef *bcd=0;
+ const ClassDef *bcd=0;
if (bmd && (bcd=bmd->getClassDef()))
{
// write class that contains a member that is reimplemented by this one
@@ -2534,7 +3017,7 @@ void MemberDefImpl::_writeReimplements(OutputList &ol)
}
}
-void MemberDefImpl::_writeReimplementedBy(OutputList &ol)
+void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const
{
MemberList *bml=reimplementedBy();
if (bml)
@@ -2542,7 +3025,7 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol)
MemberListIterator mli(*bml);
MemberDef *bmd=0;
uint count=0;
- ClassDef *bcd=0;
+ const ClassDef *bcd=0;
for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli)
{
// count the members that directly inherit from md and for
@@ -2559,7 +3042,7 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol)
ol.startParagraph();
QCString reimplInLine;
- if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface))
+ if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface))
{
reimplInLine = theTranslator->trImplementedInList(count);
}
@@ -2609,9 +3092,9 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol)
}
}
-void MemberDefImpl::_writeCategoryRelation(OutputList &ol)
+void MemberDefImpl::_writeCategoryRelation(OutputList &ol) const
{
- if (m_impl->classDef) // this should be a member of a class/category
+ if (getClassDef()) // this should be a member of a class/category
{
//printf("%s: category %s relation %s class=%s categoryOf=%s\n",
// name().data(),
@@ -2635,12 +3118,12 @@ void MemberDefImpl::_writeCategoryRelation(OutputList &ol)
text = theTranslator->trProvidedByCategory();
name = m_impl->category->displayName();
}
- else if (m_impl->classDef->categoryOf())
+ else if (getClassDef()->categoryOf())
{
// this member is part of a category so link to the corresponding class member of the class we extend
// so link to method 'categoryRelation' with 'extends class 'classDef->categoryOf()'
text = theTranslator->trExtendsClass();
- name = m_impl->classDef->categoryOf()->displayName();
+ name = getClassDef()->categoryOf()->displayName();
}
i=text.find("@0");
if (i!=-1)
@@ -2662,7 +3145,7 @@ void MemberDefImpl::_writeCategoryRelation(OutputList &ol)
}
}
-void MemberDefImpl::_writeExamples(OutputList &ol)
+void MemberDefImpl::_writeExamples(OutputList &ol) const
{
// write the list of examples that use this member
if (hasExamples())
@@ -2675,7 +3158,7 @@ void MemberDefImpl::_writeExamples(OutputList &ol)
}
}
-void MemberDefImpl::_writeTypeConstraints(OutputList &ol)
+void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const
{
if (m_impl->typeConstraints)
{
@@ -2683,15 +3166,15 @@ void MemberDefImpl::_writeTypeConstraints(OutputList &ol)
}
}
-void MemberDefImpl::_writeEnumValues(OutputList &ol,Definition *container,
+void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container,
const QCString &cfname,const QCString &ciname,
- const QCString &cname)
+ const QCString &cname) const
{
// For enum, we also write the documented enum values
if (isEnumerate())
{
bool first=TRUE;
- MemberList *fmdl=enumFieldList();
+ const MemberList *fmdl=enumFieldList();
//printf("** %s: enum values=%d\n",name().data(),fmdl!=0 ? fmdl->count() : 0);
if (fmdl)
{
@@ -2802,7 +3285,7 @@ QCString MemberDefImpl::displayDefinition() const
if (ni>=ei) ei=ni+2;
ldef = ldef.left(si) + " { ... } " + ldef.right(ldef.length()-ei);
}
- ClassDef *cd=getClassDef();
+ const ClassDef *cd=getClassDef();
if (cd && cd->isObjectiveC())
{
// strip scope name
@@ -2840,12 +3323,12 @@ QCString MemberDefImpl::displayDefinition() const
return substitute(ldef,"::",sep);
}
-void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup)
+void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup) const
{
// only write out the include file if this is not part of a class or file
// definition
static bool showGroupedMembInc = Config_getBool(SHOW_GROUPED_MEMB_INC);
- FileDef *fd = getFileDef();
+ const FileDef *fd = getFileDef();
QCString nm;
if (fd) nm = getFileDef()->docName();
if (inGroup && fd && showGroupedMembInc && !nm.isEmpty())
@@ -2884,15 +3367,15 @@ void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup)
/*! Writes the "detailed documentation" section of this member to
* all active output formats.
*/
-void MemberDefImpl::writeDocumentation(MemberList *ml,
+void MemberDefImpl::writeDocumentation(const MemberList *ml,
int memCount,int memTotal,
OutputList &ol,
const char *scName,
- Definition *container,
+ const Definition *container,
bool inGroup,
bool showEnumValues,
bool showInline
- )
+ ) const
{
// if this member is in a group find the real scope name.
bool hasParameterList = FALSE;
@@ -2913,13 +3396,13 @@ void MemberDefImpl::writeDocumentation(MemberList *ml,
QCString scopeName = scName;
QCString memAnchor = anchor();
QCString ciname = container->displayName();
- Definition *scopedContainer = container; // see bug 753608
+ const Definition *scopedContainer = container; // see bug 753608
if (container->definitionType()==TypeGroup)
{
if (getClassDef()) { scopeName=getClassDef()->displayName(); scopedContainer=getClassDef(); }
else if (getNamespaceDef()) { scopeName=getNamespaceDef()->displayName(); scopedContainer=getNamespaceDef(); }
else if (getFileDef()) { scopeName=getFileDef()->displayName(); scopedContainer=getFileDef(); }
- ciname = (dynamic_cast<GroupDef *>(container))->groupTitle();
+ ciname = (dynamic_cast<const GroupDef *>(container))->groupTitle();
}
else if (container->definitionType()==TypeFile && getNamespaceDef() && lang != SrcLangExt_Python)
{ // member is in a namespace, but is written as part of the file documentation
@@ -3048,8 +3531,8 @@ void MemberDefImpl::writeDocumentation(MemberList *ml,
ol.endMemberDocPrefixItem();
}
- ClassDef *cd=getClassDef();
- NamespaceDef *nd=getNamespaceDef();
+ const ClassDef *cd=getClassDef();
+ const NamespaceDef *nd=getNamespaceDef();
if (!Config_getBool(HIDE_SCOPE_NAMES))
{
bool first=TRUE;
@@ -3163,7 +3646,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml,
ldef.left(pos)
);
ol.docify(ldef.mid(pos));
- Definition *scope = cd;
+ const Definition *scope = cd;
if (scope==0) scope = nd;
hasParameterList=writeDefArgumentList(ol,scope,this);
}
@@ -3175,7 +3658,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml,
this,
substitute(ldef,"::",sep)
);
- Definition *scope = cd;
+ const Definition *scope = cd;
if (scope==0) scope = nd;
hasParameterList=writeDefArgumentList(ol,scope,this);
}
@@ -3276,7 +3759,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml,
ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
pIntf->resetCodeParserState();
ol.startCodeFragment();
- pIntf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,getFileDef(),
+ pIntf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()),
-1,-1,TRUE,this,FALSE,this);
ol.endCodeFragment();
}
@@ -3475,7 +3958,7 @@ QCString MemberDefImpl::fieldType() const
return simplifyTypeForTable(type);
}
-void MemberDefImpl::writeMemberDocSimple(OutputList &ol, Definition *container)
+void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *container) const
{
Definition *scope = getOuterScope();
QCString doxyName = name();
@@ -3493,7 +3976,7 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, Definition *container)
//printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>");
if (container && container->definitionType()==Definition::TypeClass &&
- !(dynamic_cast<ClassDef*>(container))->isJavaEnum())
+ !(dynamic_cast<const ClassDef*>(container))->isJavaEnum())
{
ol.startInlineMemberType();
ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
@@ -3594,17 +4077,17 @@ QCString MemberDefImpl::memberTypeName() const
}
}
-void MemberDefImpl::warnIfUndocumented()
+void MemberDefImpl::warnIfUndocumented() const
{
/*
* Removed bug_303020:
* if (m_impl->memberGroup) return;
*/
- ClassDef *cd = getClassDef();
- NamespaceDef *nd = getNamespaceDef();
- FileDef *fd = getFileDef();
- GroupDef *gd = getGroupDef();
- Definition *d=0;
+ const ClassDef *cd = getClassDef();
+ const NamespaceDef *nd = getNamespaceDef();
+ const FileDef *fd = getFileDef();
+ const GroupDef *gd = getGroupDef();
+ const Definition *d=0;
const char *t=0;
if (cd)
t="class", d=cd;
@@ -3641,22 +4124,114 @@ void MemberDefImpl::warnIfUndocumented()
}
}
+void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const
+{
+ if (!Config_getBool(WARN_NO_PARAMDOC)) return;
+ QCString returnType = typeString();
+ bool isPython = getLanguage()==SrcLangExt_Python;
+
+ if (!m_impl->hasDocumentedParams && hasParamCommand)
+ {
+ //printf("%s:hasDocumentedParams=TRUE;\n",name().data());
+ m_impl->hasDocumentedParams = TRUE;
+ }
+ else if (!m_impl->hasDocumentedParams)
+ {
+ const ArgumentList *al = argumentList();
+ const ArgumentList *declAl = declArgumentList();
+ bool allDoc=TRUE; // no parameter => all parameters are documented
+ if ( // member has parameters
+ al!=0 && // but the member has a parameter list
+ al->count()>0 // with at least one parameter (that is not void)
+ )
+ {
+ ArgumentListIterator ali(*al);
+ Argument *a;
+
+ // see if all parameters have documentation
+ for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
+ {
+ if (!a->name.isEmpty() && a->type!="void" &&
+ !(isPython && (a->name=="self" || a->name=="cls"))
+ )
+ {
+ allDoc = !a->docs.isEmpty();
+ }
+ //printf("a->type=%s a->name=%s doc=%s\n",
+ // a->type.data(),a->name.data(),a->docs.data());
+ }
+ if (!allDoc && declAl!=0) // try declaration arguments as well
+ {
+ allDoc=TRUE;
+ ArgumentListIterator ali(*declAl);
+ Argument *a;
+ for (ali.toFirst();(a=ali.current()) && allDoc;++ali)
+ {
+ if (!a->name.isEmpty() && a->type!="void" &&
+ !(isPython && (a->name=="self" || a->name=="cls"))
+ )
+ {
+ allDoc = !a->docs.isEmpty();
+ }
+ //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data());
+ }
+ }
+ }
+ if (allDoc)
+ {
+ //printf("%s:hasDocumentedParams=TRUE;\n",name().data());
+ m_impl->hasDocumentedParams = TRUE;
+ }
+ }
+
+ //printf("Member %s hasDocumentedReturnType=%d hasReturnCommand=%d\n",
+ // name().data(),m_impl->hasDocumentedReturnType,hasReturnCommand);
+ if (!m_impl->hasDocumentedReturnType && // docs not yet found
+ hasReturnCommand)
+ {
+ m_impl->hasDocumentedReturnType = TRUE;
+ }
+ else if ( // see if return type is documented in a function w/o return type
+ hasReturnCommand &&
+ (
+ returnType.find("void")!=-1 || // void return type
+ returnType.find("subroutine")!=-1 || // fortran subroutine
+ isConstructor() || // a constructor
+ isDestructor() // or destructor
+ )
+ )
+ {
+ warn_doc_error(getDefFileName(),getDefLine(),"documented empty return type of %s",
+ qualifiedName().data());
+ }
+ else if ( // see if return needs to documented
+ m_impl->hasDocumentedReturnType ||
+ returnType.find("void")!=-1 || // void return type
+ returnType.find("subroutine")!=-1 || // fortran subroutine
+ isConstructor() || // a constructor
+ isDestructor() // or destructor
+ )
+ {
+ m_impl->hasDocumentedReturnType = TRUE;
+ }
+}
-void MemberDefImpl::warnIfUndocumentedParams()
+void MemberDefImpl::warnIfUndocumentedParams() const
{
if (!Config_getBool(EXTRACT_ALL) &&
Config_getBool(WARN_IF_UNDOCUMENTED) &&
Config_getBool(WARN_NO_PARAMDOC) &&
+ !isDeleted() &&
!isReference() &&
!Doxygen::suppressDocWarnings)
{
- if (!hasDocumentedParams())
+ if (!m_impl->hasDocumentedParams)
{
warn_doc_error(getDefFileName(),getDefLine(),
"parameters of member %s are not (all) documented",
qPrint(qualifiedName()));
}
- if (!hasDocumentedReturnType() &&
+ if (!m_impl->hasDocumentedReturnType &&
isFunction() && hasDocumentation())
{
warn_doc_error(getDefFileName(),getDefLine(),
@@ -3709,7 +4284,7 @@ void MemberDefImpl::setMemberGroup(MemberGroup *grp)
m_impl->memberGroup = grp;
}
-bool MemberDefImpl::visibleMemberGroup(bool hideNoHeader)
+bool MemberDefImpl::visibleMemberGroup(bool hideNoHeader) const
{
return m_impl->memberGroup!=0 &&
(!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]");
@@ -3821,7 +4396,7 @@ void MemberDefImpl::setNamespace(NamespaceDef *nd)
}
MemberDef *MemberDefImpl::createTemplateInstanceMember(
- ArgumentList *formalArgs,ArgumentList *actualArgs)
+ ArgumentList *formalArgs,ArgumentList *actualArgs) const
{
//printf(" Member %s %s %s\n",typeString(),name().data(),argsString());
ArgumentList *actualArgList = 0;
@@ -3954,7 +4529,7 @@ void MemberDefImpl::addListReference(Definition *)
}
}
-MemberList *MemberDefImpl::getSectionList(Definition *d) const
+const MemberList *MemberDefImpl::getSectionList(const Definition *d) const
{
char key[20];
sprintf(key,"%p",d);
@@ -3993,7 +4568,7 @@ Specifier MemberDefImpl::virtualness(int count) const
return v;
}
-void MemberDefImpl::writeTagFile(FTextStream &tagFile)
+void MemberDefImpl::writeTagFile(FTextStream &tagFile) const
{
if (!isLinkableInProject()) return;
tagFile << " <member kind=\"";
@@ -4077,7 +4652,7 @@ void MemberDefImpl::writeTagFile(FTextStream &tagFile)
void MemberDefImpl::_computeIsConstructor()
{
m_isConstructorCached=1; // FALSE
- if (m_impl->classDef)
+ if (getClassDef())
{
if (m_impl->isDMember) // for D
{
@@ -4102,7 +4677,7 @@ void MemberDefImpl::_computeIsConstructor()
}
else // for other languages
{
- QCString locName = m_impl->classDef->localName();
+ QCString locName = getClassDef()->localName();
int i=locName.find('<');
if (i==-1) // not a template class
{
@@ -4170,7 +4745,7 @@ bool MemberDefImpl::isDestructor() const
}
void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd)
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const
{
int enumMemCount=0;
@@ -4387,13 +4962,13 @@ void MemberDefImpl::setInbodyDocumentation(const char *docs,
bool MemberDefImpl::isObjCMethod() const
{
- if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE;
+ if (getClassDef() && getClassDef()->isObjectiveC() && isFunction()) return TRUE;
return FALSE;
}
bool MemberDefImpl::isObjCProperty() const
{
- if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isProperty()) return TRUE;
+ if (getClassDef() && getClassDef()->isObjectiveC() && isProperty()) return TRUE;
return FALSE;
}
@@ -4404,7 +4979,7 @@ QCString MemberDefImpl::qualifiedName() const
QCString qm;
if (isStatic()) qm="+"; else qm="-";
qm+="[";
- qm+=m_impl->classDef->name()+" ";
+ qm+=getClassDef()->name()+" ";
qm+=name();
qm+="]";
return qm;
@@ -4443,7 +5018,7 @@ QCString MemberDefImpl::objCMethodName(bool localLink,bool showStatic) const
if (!localLink) // link to method of same class
{
qm+=" (";
- qm+=m_impl->classDef->name();
+ qm+=getClassDef()->name();
qm+=")";
}
return qm;
@@ -4499,17 +5074,32 @@ uint64 MemberDefImpl::getMemberSpecifiers() const
return m_impl->memSpec;
}
-ClassDef *MemberDefImpl::getClassDef() const
+const ClassDef *MemberDefImpl::getClassDef() const
+{
+ return m_impl->classDef;
+}
+
+ClassDef *MemberDefImpl::getClassDef()
{
return m_impl->classDef;
}
-FileDef *MemberDefImpl::getFileDef() const
+const FileDef *MemberDefImpl::getFileDef() const
+{
+ return m_impl->fileDef;
+}
+
+FileDef *MemberDefImpl::getFileDef()
{
return m_impl->fileDef;
}
-NamespaceDef* MemberDefImpl::getNamespaceDef() const
+const NamespaceDef* MemberDefImpl::getNamespaceDef() const
+{
+ return m_impl->nspace;
+}
+
+NamespaceDef* MemberDefImpl::getNamespaceDef()
{
return m_impl->nspace;
}
@@ -4524,7 +5114,12 @@ const char *MemberDefImpl::getWriteAccessor() const
return m_impl->write;
}
-GroupDef *MemberDefImpl::getGroupDef() const
+const GroupDef *MemberDefImpl::getGroupDef() const
+{
+ return m_impl->group;
+}
+
+GroupDef *MemberDefImpl::getGroupDef()
{
return m_impl->group;
}
@@ -4801,7 +5396,7 @@ bool MemberDefImpl::isUnretained() const
return (m_impl->memSpec&Entry::Unretained)!=0;
}
-bool MemberDefImpl::isAlias() const
+bool MemberDefImpl::isTypeAlias() const
{
return (m_impl->memSpec&Entry::Alias)!=0;
}
@@ -4887,16 +5482,6 @@ bool MemberDefImpl::isTemplateSpecialization() const
return m_impl->tspec;
}
-bool MemberDefImpl::hasDocumentedParams() const
-{
- return m_impl->hasDocumentedParams;
-}
-
-bool MemberDefImpl::hasDocumentedReturnType() const
-{
- return m_impl->hasDocumentedReturnType;
-}
-
bool MemberDefImpl::showInCallGraph() const
{
return isFunction() ||
@@ -4916,7 +5501,7 @@ bool MemberDefImpl::hasDocumentedEnumValues() const
return m_impl->docEnumValues;
}
-MemberDef *MemberDefImpl::getAnonymousEnumType() const
+const MemberDef *MemberDefImpl::getAnonymousEnumType() const
{
return m_impl->annEnumType;
}
@@ -4926,7 +5511,7 @@ bool MemberDefImpl::isDocsForDefinition() const
return m_impl->docsForDefinition;
}
-MemberDef *MemberDefImpl::getEnumScope() const
+const MemberDef *MemberDefImpl::getEnumScope() const
{
return m_impl->enumScope;
}
@@ -4946,7 +5531,7 @@ bool MemberDefImpl::isConstExpr() const
return (m_impl->memSpec&Entry::ConstExpr)!=0;
}
-MemberList *MemberDefImpl::enumFieldList() const
+const MemberList *MemberDefImpl::enumFieldList() const
{
return m_impl->enumFields;
}
@@ -4961,22 +5546,27 @@ bool MemberDefImpl::isPrototype() const
return m_impl->proto;
}
-ArgumentList *MemberDefImpl::argumentList() const
+const ArgumentList *MemberDefImpl::argumentList() const
+{
+ return m_impl->defArgList;
+}
+
+ArgumentList *MemberDefImpl::argumentList()
{
return m_impl->defArgList;
}
-ArgumentList *MemberDefImpl::declArgumentList() const
+const ArgumentList *MemberDefImpl::declArgumentList() const
{
return m_impl->declArgList;
}
-ArgumentList *MemberDefImpl::templateArguments() const
+const ArgumentList *MemberDefImpl::templateArguments() const
{
return m_impl->tArgList;
}
-QList<ArgumentList> *MemberDefImpl::definitionTemplateParameterLists() const
+const QList<ArgumentList> *MemberDefImpl::definitionTemplateParameterLists() const
{
return m_impl->defTmpArgLists;
}
@@ -5001,7 +5591,7 @@ bool MemberDefImpl::anonymousDeclShown() const
return m_impl->annUsed;
}
-void MemberDefImpl::setAnonymousUsed()
+void MemberDefImpl::setAnonymousUsed() const
{
m_impl->annUsed = TRUE;
}
@@ -5036,7 +5626,7 @@ bool MemberDefImpl::isTypedefValCached() const
return m_impl->isTypedefValCached;
}
-ClassDef *MemberDefImpl::getCachedTypedefVal() const
+const ClassDef *MemberDefImpl::getCachedTypedefVal() const
{
return m_impl->cachedTypedefValue;
}
@@ -5067,7 +5657,7 @@ MemberDef *MemberDefImpl::inheritsDocsFrom() const
return m_impl->docProvider;
}
-MemberDef *MemberDefImpl::getGroupAlias() const
+const MemberDef *MemberDefImpl::getGroupAlias() const
{
return m_impl->groupAlias;
}
@@ -5165,16 +5755,6 @@ void MemberDefImpl::makeForeign()
m_isLinkableCached = 0;
}
-void MemberDefImpl::setHasDocumentedParams(bool b)
-{
- m_impl->hasDocumentedParams = b;
-}
-
-void MemberDefImpl::setHasDocumentedReturnType(bool b)
-{
- m_impl->hasDocumentedReturnType = b;
-}
-
void MemberDefImpl::setInheritsDocsFrom(MemberDef *md)
{
m_impl->docProvider = md;
@@ -5202,7 +5782,7 @@ void MemberDefImpl::setDocumentedEnumValues(bool value)
m_impl->docEnumValues=value;
}
-void MemberDefImpl::setAnonymousEnumType(MemberDef *md)
+void MemberDefImpl::setAnonymousEnumType(const MemberDef *md)
{
m_impl->annEnumType = md;
}
@@ -5251,7 +5831,7 @@ void MemberDefImpl::makeImplementationDetail()
m_impl->implOnly=TRUE;
}
-void MemberDefImpl::setFromAnonymousScope(bool b)
+void MemberDefImpl::setFromAnonymousScope(bool b) const
{
m_impl->annScope=b;
}
@@ -5277,7 +5857,7 @@ void MemberDefImpl::setDocsForDefinition(bool b)
m_impl->docsForDefinition = b;
}
-void MemberDefImpl::setGroupAlias(MemberDef *md)
+void MemberDefImpl::setGroupAlias(const MemberDef *md)
{
m_impl->groupAlias = md;
}
@@ -5328,7 +5908,7 @@ QCString MemberDefImpl::enumBaseType() const
}
-void MemberDefImpl::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
+void MemberDefImpl::cacheTypedefVal(const ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
{
m_impl->isTypedefValCached=TRUE;
m_impl->cachedTypedefValue=val;
@@ -5340,28 +5920,32 @@ void MemberDefImpl::cacheTypedefVal(ClassDef*val, const QCString & templSpec, co
void MemberDefImpl::copyArgumentNames(MemberDef *bmd)
{
{
- ArgumentList *arguments = bmd->argumentList();
+ const ArgumentList *arguments = bmd->argumentList();
if (m_impl->defArgList && arguments)
{
ArgumentListIterator aliDst(*m_impl->defArgList);
ArgumentListIterator aliSrc(*arguments);
- Argument *argDst, *argSrc;
+ Argument *argDst;
+ const Argument *argSrc;
for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
{
argDst->name = argSrc->name;
+ argDst->docs = argSrc->docs;
}
}
}
{
- ArgumentList *arguments = bmd->declArgumentList();
+ const ArgumentList *arguments = bmd->declArgumentList();
if (m_impl->declArgList && arguments)
{
ArgumentListIterator aliDst(*m_impl->declArgList);
ArgumentListIterator aliSrc(*arguments);
- Argument *argDst, *argSrc;
+ Argument *argDst;
+ const Argument *argSrc;
for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
{
argDst->name = argSrc->name;
+ argDst->docs = argSrc->docs;
}
}
}
@@ -5393,7 +5977,7 @@ QCString MemberDefImpl::displayName(bool) const
return DefinitionImpl::name();
}
-void MemberDefImpl::addToSearchIndex()
+void MemberDefImpl::addToSearchIndex() const
{
// write search index info
if (Doxygen::searchIndex && isLinkableInProject())
@@ -5459,12 +6043,14 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef)
// mdef, mdef ? mdef->name().data() : "",
// mdec, mdec ? mdec->name().data() : "");
+ const MemberDef *cmdec = const_cast<const MemberDef*>(mdec);
+ const MemberDef *cmdef = const_cast<const MemberDef*>(mdef);
ArgumentList *mdefAl = mdef->argumentList();
ArgumentList *mdecAl = mdec->argumentList();
- if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl,
- mdec->getOuterScope(),mdec->getFileDef(),mdecAl,
- TRUE
- )
+ if (matchArguments2(cmdef->getOuterScope(),cmdef->getFileDef(),mdefAl,
+ cmdec->getOuterScope(),cmdec->getFileDef(),mdecAl,
+ TRUE
+ )
) /* match found */
{
//printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n",
diff --git a/src/memberdef.h b/src/memberdef.h
index 555935a..af4fb0a 100644
--- a/src/memberdef.h
+++ b/src/memberdef.h
@@ -47,6 +47,9 @@ class MemberDef : virtual public Definition
// move this member into a different scope
virtual MemberDef *deepCopy() const =0;
virtual void moveTo(Definition *) = 0;
+
+ virtual MemberDef *resolveAlias() = 0;
+ virtual const MemberDef *resolveAlias() const = 0;
//-----------------------------------------------------------------------------------
// ---- getters -----
@@ -67,13 +70,22 @@ class MemberDef : virtual public Definition
virtual const QCString &initializer() const = 0;
virtual int initializerLines() const = 0;
virtual uint64 getMemberSpecifiers() const = 0;
- virtual MemberList *getSectionList(Definition *d) const = 0;
+ virtual const MemberList *getSectionList(const Definition *d) const = 0;
virtual QCString displayDefinition() const = 0;
// scope query members
- virtual ClassDef *getClassDef() const = 0;
- virtual FileDef *getFileDef() const = 0;
- virtual NamespaceDef* getNamespaceDef() const = 0;
+ virtual const ClassDef *getClassDef() const = 0;
+ virtual ClassDef *getClassDef() = 0;
+
+ virtual const FileDef *getFileDef() const = 0;
+ virtual FileDef *getFileDef() = 0;
+
+ virtual const NamespaceDef* getNamespaceDef() const = 0;
+ virtual NamespaceDef* getNamespaceDef() = 0;
+
+ virtual const GroupDef *getGroupDef() const = 0;
+ virtual GroupDef *getGroupDef() = 0;
+
virtual ClassDef *accessorClass() const = 0;
// grabbing the property read/write accessor names
@@ -81,7 +93,6 @@ class MemberDef : virtual public Definition
virtual const char *getWriteAccessor() const = 0;
// querying the grouping definition
- virtual GroupDef *getGroupDef() const = 0;
virtual Grouping::GroupPri_t getGroupPri() const = 0;
virtual const char *getGroupFileName() const = 0;
virtual int getGroupStartLine() const = 0;
@@ -145,7 +156,7 @@ class MemberDef : virtual public Definition
virtual bool isSealed() const = 0;
virtual bool isImplementation() const = 0;
virtual bool isExternal() const = 0;
- virtual bool isAlias() const = 0;
+ virtual bool isTypeAlias() const = 0;
virtual bool isDefault() const = 0;
virtual bool isDelete() const = 0;
virtual bool isNoExcept() const = 0;
@@ -160,8 +171,6 @@ class MemberDef : virtual public Definition
virtual bool isMaybeAmbiguous() const = 0;
virtual bool isPublished() const = 0; // UNO IDL published
virtual bool isTemplateSpecialization() const = 0;
- virtual bool hasDocumentedParams() const = 0;
- virtual bool hasDocumentedReturnType() const = 0;
virtual bool isObjCMethod() const = 0;
virtual bool isObjCProperty() const = 0;
virtual bool isConstructor() const = 0;
@@ -194,27 +203,28 @@ class MemberDef : virtual public Definition
virtual MemberDef *reimplements() const = 0;
virtual MemberList *reimplementedBy() const = 0;
- virtual bool isReimplementedBy(ClassDef *cd) const = 0;
+ virtual bool isReimplementedBy(const ClassDef *cd) const = 0;
virtual ClassDef *relatedAlso() const = 0;
virtual bool hasDocumentedEnumValues() const = 0;
- virtual MemberDef *getAnonymousEnumType() const = 0;
+ virtual const MemberDef *getAnonymousEnumType() const = 0;
virtual bool isDocsForDefinition() const = 0;
- virtual MemberDef *getEnumScope() const = 0;
- virtual MemberList *enumFieldList() const = 0;
+ virtual const MemberDef *getEnumScope() const = 0;
+ virtual const MemberList *enumFieldList() const = 0;
virtual void setEnumBaseType(const QCString &type) = 0;
virtual QCString enumBaseType() const = 0;
- virtual bool hasExamples() = 0;
+ virtual bool hasExamples() const = 0;
virtual ExampleSDict *getExamples() const = 0;
virtual bool isPrototype() const = 0;
// argument related members
- virtual ArgumentList *argumentList() const = 0;
- virtual ArgumentList *declArgumentList() const = 0;
- virtual ArgumentList *templateArguments() const = 0;
- virtual QList<ArgumentList> *definitionTemplateParameterLists() const = 0;
+ virtual const ArgumentList *argumentList() const = 0;
+ virtual ArgumentList *argumentList() = 0;
+ virtual const ArgumentList *declArgumentList() const = 0;
+ virtual const ArgumentList *templateArguments() const = 0;
+ virtual const QList<ArgumentList> *definitionTemplateParameterLists() const = 0;
// member group related members
virtual int getMemberGroupId() const = 0;
@@ -227,32 +237,32 @@ class MemberDef : virtual public Definition
// callgraph related members
virtual bool hasCallGraph() const = 0;
virtual bool hasCallerGraph() const = 0;
- virtual bool visibleMemberGroup(bool hideNoHeader) = 0;
+ virtual bool visibleMemberGroup(bool hideNoHeader) const = 0;
// refrenced related members
virtual bool hasReferencesRelation() const = 0;
virtual bool hasReferencedByRelation() const = 0;
virtual MemberDef *templateMaster() const = 0;
virtual QCString getScopeString() const = 0;
- virtual ClassDef *getClassDefOfAnonymousType() = 0;
+ virtual ClassDef *getClassDefOfAnonymousType() const = 0;
// cached typedef functions
virtual bool isTypedefValCached() const = 0;
- virtual ClassDef *getCachedTypedefVal() const = 0;
+ virtual const ClassDef *getCachedTypedefVal() const = 0;
virtual QCString getCachedTypedefTemplSpec() const = 0;
virtual QCString getCachedResolvedTypedef() const = 0;
virtual MemberDef *memberDefinition() const = 0;
virtual MemberDef *memberDeclaration() const = 0;
virtual MemberDef *inheritsDocsFrom() const = 0;
- virtual MemberDef *getGroupAlias() const = 0;
+ virtual const MemberDef *getGroupAlias() const = 0;
virtual ClassDef *category() const = 0;
virtual MemberDef *categoryRelation() const = 0;
virtual QCString displayName(bool=TRUE) const = 0;
virtual QCString getDeclType() const = 0;
- virtual void getLabels(QStrList &sl,Definition *container) const = 0;
+ virtual void getLabels(QStrList &sl,const Definition *container) const = 0;
virtual const ArgumentList *typeConstraints() const = 0;
@@ -292,8 +302,6 @@ class MemberDef : virtual public Definition
virtual void makeRelated() = 0;
virtual void makeForeign() = 0;
- virtual void setHasDocumentedParams(bool b) = 0;
- virtual void setHasDocumentedReturnType(bool b) = 0;
virtual void setInheritsDocsFrom(MemberDef *md) = 0;
virtual void setTagInfo(TagInfo *i) = 0;
virtual void setArgsString(const char *as) = 0;
@@ -309,7 +317,7 @@ class MemberDef : virtual public Definition
virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE) = 0;
virtual void setEnumClassScope(ClassDef *cd) = 0;
virtual void setDocumentedEnumValues(bool value) = 0;
- virtual void setAnonymousEnumType(MemberDef *md) = 0;
+ virtual void setAnonymousEnumType(const MemberDef *md) = 0;
// example related members
virtual bool addExample(const char *anchor,const char *name,const char *file) = 0;
@@ -336,7 +344,6 @@ class MemberDef : virtual public Definition
virtual void makeImplementationDetail() = 0;
// anonymous scope members
- virtual void setFromAnonymousScope(bool b) = 0;
virtual void setFromAnonymousMember(MemberDef *m) = 0;
virtual void enableCallGraph(bool e) = 0;
@@ -348,18 +355,17 @@ class MemberDef : virtual public Definition
virtual void setTemplateMaster(MemberDef *mt) = 0;
virtual void addListReference(Definition *d) = 0;
virtual void setDocsForDefinition(bool b) = 0;
- virtual void setGroupAlias(MemberDef *md) = 0;
+ virtual void setGroupAlias(const MemberDef *md) = 0;
- virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0;
+ virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0;
virtual void invalidateTypedefValCache() = 0;
virtual void invalidateCachedArgumentTypes() = 0;
-
+
// declaration <-> definition relation
virtual void setMemberDefinition(MemberDef *md) = 0;
virtual void setMemberDeclaration(MemberDef *md) = 0;
-
- virtual void setAnonymousUsed() = 0;
+
virtual void copyArgumentNames(MemberDef *bmd) = 0;
virtual void setCategory(ClassDef *) = 0;
@@ -375,29 +381,36 @@ class MemberDef : virtual public Definition
// --- actions ----
//-----------------------------------------------------------------------------------
- // output generation
- virtual void writeDeclaration(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool inGroup, ClassDef *inheritFrom=0,const char *inheritId=0) = 0;
- virtual void writeDocumentation(MemberList *ml,int memCount,int memTotal,OutputList &ol,
- const char *scopeName,Definition *container,
- bool inGroup,bool showEnumValues=FALSE,bool
- showInline=FALSE) = 0;
- virtual void writeMemberDocSimple(OutputList &ol,Definition *container) = 0;
- virtual void writeEnumDeclaration(OutputList &typeDecl,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd) = 0;
- virtual void writeTagFile(FTextStream &) = 0;
- virtual void warnIfUndocumented() = 0;
- virtual void warnIfUndocumentedParams() = 0;
-
virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs,
- ArgumentList *actualArgs) = 0;
-
+ ArgumentList *actualArgs) const = 0;
virtual void findSectionsInDocumentation() = 0;
+ virtual void addToSearchIndex() const = 0;
+
+ //-----------------------------------------------------------------------------------
+ // --- write output ----
+ //-----------------------------------------------------------------------------------
+
+ virtual void writeDeclaration(OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const = 0;
+ virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol,
+ const char *scopeName,const Definition *container,
+ bool inGroup,bool showEnumValues=FALSE,bool
+ showInline=FALSE) const = 0;
+ virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const = 0;
+ virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd,
+ const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0;
+ virtual void writeTagFile(FTextStream &) const = 0;
virtual void writeLink(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool onlyText=FALSE) = 0;
- virtual void addToSearchIndex() = 0;
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool onlyText=FALSE) const = 0;
+
+ // write helpers
+ virtual void warnIfUndocumented() const = 0;
+ virtual void warnIfUndocumentedParams() const = 0;
+ virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0;
+ virtual void setAnonymousUsed() const = 0;
+ virtual void setFromAnonymousScope(bool b) const = 0;
};
@@ -408,6 +421,8 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn,
Relationship related,MemberType t,const ArgumentList *tal,
const ArgumentList *al,const char *metaData);
+MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd);
+
void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef);
#endif
diff --git a/src/membergroup.cpp b/src/membergroup.cpp
index 9c48668..04689b4 100644
--- a/src/membergroup.cpp
+++ b/src/membergroup.cpp
@@ -40,7 +40,7 @@ MemberGroup::MemberGroup()
{
}
-MemberGroup::MemberGroup(Definition *parent,
+MemberGroup::MemberGroup(const Definition *parent,
int id,const char *hdr,const char *d,const char *docFile,int docLine)
{
static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
@@ -51,7 +51,6 @@ MemberGroup::MemberGroup(Definition *parent,
grpId = id;
grpHeader = hdr;
doc = d;
- scope = 0;
inSameSection = TRUE;
inDeclSection = 0;
m_numDecMembers = -1;
@@ -86,14 +85,14 @@ void MemberGroup::insertMember(MemberDef *md)
}
else if (inDeclSection==0)
{
- inDeclSection = md->getSectionList(m_parent);
+ inDeclSection = const_cast<MemberList*>(md->getSectionList(m_parent));
//printf("inDeclSection=%p type=%d\n",inDeclSection,inDeclSection->listType());
}
memberList->append(md);
// copy the group of the first member in the memberGroup
GroupDef *gd;
- if (firstMd && (gd=firstMd->getGroupDef()))
+ if (firstMd && (gd=const_cast<GroupDef*>(firstMd->getGroupDef())))
{
md->setGroupDef(gd, firstMd->getGroupPri(),
firstMd->getGroupFileName(), firstMd->getGroupStartLine(),
@@ -109,8 +108,8 @@ void MemberGroup::setAnchors()
}
void MemberGroup::writeDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool showInline)
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool showInline) const
{
//printf("MemberGroup::writeDeclarations() %s\n",grpHeader.data());
QCString ldoc = doc;
@@ -119,29 +118,34 @@ void MemberGroup::writeDeclarations(OutputList &ol,
}
void MemberGroup::writePlainDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- ClassDef *inheritedFrom,const char *inheritId
- )
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ const ClassDef *inheritedFrom,const char *inheritId
+ ) const
{
//printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count());
memberList->writePlainDeclarations(ol,cd,nd,fd,gd,inheritedFrom,inheritId);
}
void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName,
- Definition *container,bool showEnumValues,bool showInline)
+ const Definition *container,bool showEnumValues,bool showInline) const
{
memberList->writeDocumentation(ol,scopeName,container,0,showEnumValues,showInline);
}
void MemberGroup::writeDocumentationPage(OutputList &ol,const char *scopeName,
- Definition *container)
+ const Definition *container) const
{
memberList->writeDocumentationPage(ol,scopeName,container);
}
-void MemberGroup::addGroupedInheritedMembers(OutputList &ol,ClassDef *cd,
+void MemberGroup::setAnonymousEnumType()
+{
+ memberList->setAnonymousEnumType();
+}
+
+void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd,
MemberListType lt,
- ClassDef *inheritedFrom,const QCString &inheritId)
+ const ClassDef *inheritedFrom,const QCString &inheritId) const
{
//printf("** addGroupedInheritedMembers()\n");
MemberListIterator li(*memberList);
@@ -149,11 +153,12 @@ void MemberGroup::addGroupedInheritedMembers(OutputList &ol,ClassDef *cd,
for (li.toFirst();(md=li.current());++li)
{
//printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType());
- MemberList *ml = md->getSectionList(m_parent);
+ const MemberList *ml = md->getSectionList(m_parent);
if (ml && lt==ml->listType())
{
MemberList ml(lt);
ml.append(md);
+ ml.countDecMembers();
ml.writePlainDeclarations(ol,cd,0,0,0,inheritedFrom,inheritId);
}
}
@@ -168,7 +173,7 @@ int MemberGroup::countGroupedInheritedMembers(MemberListType lt)
for (li.toFirst();(md=li.current());++li)
{
//printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType());
- MemberList *ml = md->getSectionList(m_parent);
+ const MemberList *ml = md->getSectionList(m_parent);
if (ml && lt==ml->listType())
{
count++;
@@ -185,33 +190,24 @@ void MemberGroup::addToDeclarationSection()
{
if (inDeclSection)
{
- //printf("Adding group %p to list %p (type=%d)\n",this,
- // inDeclSection,inDeclSection->listType());
+ //printf("Adding group %p to list %p (type=%d) memberList=%p\n",this,
+ // inDeclSection,inDeclSection->listType(),memberList);
inDeclSection->addMemberGroup(this);
}
}
-int MemberGroup::countDecMembers(GroupDef *gd)
+void MemberGroup::countDecMembers()
{
- if (m_numDecMembers==-1) /* number of member not cached */
- {
- memberList->countDecMembers(gd);
- m_numDecMembers = memberList->numDecMembers();
- }
- return m_numDecMembers;
+ memberList->countDecMembers();
}
-int MemberGroup::countDocMembers()
+void MemberGroup::countDocMembers()
{
- if (m_numDocMembers==-1)
- {
- memberList->countDocMembers();
- m_numDocMembers = memberList->numDocMembers();
- }
- return m_numDocMembers;
+ memberList->countDocMembers();
}
-int MemberGroup::countInheritableMembers(ClassDef *inheritedFrom) const
+
+int MemberGroup::countInheritableMembers(const ClassDef *inheritedFrom) const
{
return memberList->countInheritableMembers(inheritedFrom);
}
@@ -255,6 +251,7 @@ void MemberGroup::distributeMemberGroupDocumentation()
}
}
+#if 0
int MemberGroup::varCount() const
{
return memberList->varCount();
@@ -304,15 +301,26 @@ int MemberGroup::friendCount() const
{
return memberList->friendCount();
}
+#endif
-int MemberGroup::numDecMembers() const
-{
- return memberList->numDecMembers();
+int MemberGroup::numDecMembers() const
+{
+ return memberList->numDecMembers();
}
-int MemberGroup::numDocMembers() const
-{
- return memberList->numDocMembers();
+int MemberGroup::numDecEnumValues() const
+{
+ return memberList->numDecEnumValues();
+}
+
+int MemberGroup::numDocMembers() const
+{
+ return memberList->numDocMembers();
+}
+
+int MemberGroup::numDocEnumValues() const
+{
+ return memberList->numDocEnumValues();
}
void MemberGroup::setInGroup(bool b)
@@ -320,6 +328,7 @@ void MemberGroup::setInGroup(bool b)
memberList->setInGroup(b);
}
+
QCString MemberGroup::anchor() const
{
uchar md5_sig[16];
diff --git a/src/membergroup.h b/src/membergroup.h
index 51123bb..c07d025 100644
--- a/src/membergroup.h
+++ b/src/membergroup.h
@@ -41,7 +41,7 @@ class MemberGroup
{
public:
MemberGroup();
- MemberGroup(Definition *parent,int id,const char *header,
+ MemberGroup(const Definition *parent,int id,const char *header,
const char *docs,const char *docFile,int docLine);
~MemberGroup();
QCString header() const { return grpHeader; }
@@ -49,28 +49,30 @@ class MemberGroup
void insertMember(MemberDef *md);
void setAnchors();
void writePlainDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- ClassDef *inheritedFrom,const char *inheritId);
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ const ClassDef *inheritedFrom,const char *inheritId) const;
void writeDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
- bool showInline=FALSE);
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ bool showInline=FALSE) const;
void writeDocumentation(OutputList &ol,const char *scopeName,
- Definition *container,bool showEnumValues,bool showInline);
+ const Definition *container,bool showEnumValues,bool showInline) const;
void writeDocumentationPage(OutputList &ol,const char *scopeName,
- Definition *container);
+ const Definition *container) const;
void writeTagFile(FTextStream &);
- void addGroupedInheritedMembers(OutputList &ol,ClassDef *cd,
+ void addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd,
MemberListType lt,
- ClassDef *inheritedFrom,const QCString &inheritId);
+ const ClassDef *inheritedFrom,const QCString &inheritId) const;
+ void setAnonymousEnumType();
const QCString &documentation() const { return doc; }
bool allMembersInSameSection() const { return inSameSection; }
void addToDeclarationSection();
- int countDecMembers(GroupDef *gd=0);
- int countDocMembers();
+ void countDecMembers();
+ void countDocMembers();
int countGroupedInheritedMembers(MemberListType lt);
void distributeMemberGroupDocumentation();
void findSectionsInDocumentation();
+ /*
int varCount() const;
int funcCount() const;
int enumCount() const;
@@ -81,14 +83,18 @@ class MemberGroup
int protoCount() const;
int defineCount() const;
int friendCount() const;
+ */
int numDecMembers() const;
+ int numDecEnumValues() const;
int numDocMembers() const;
- int countInheritableMembers(ClassDef *inheritedFrom) const;
+ int numDocEnumValues() const;
+
+ int countInheritableMembers(const ClassDef *inheritedFrom) const;
void setInGroup(bool b);
void addListReferences(Definition *d);
void setRefItems(const QList<ListItemInfo> *sli);
MemberList *members() const { return memberList; }
- Definition *parent() const { return m_parent; }
+ const Definition *parent() const { return m_parent; }
QCString anchor() const;
QCString docFile() const { return m_docFile; }
@@ -100,12 +106,11 @@ class MemberGroup
int grpId;
QCString grpHeader;
QCString fileName; // base name of the generated file
- Definition *scope;
QCString doc;
bool inSameSection;
int m_numDecMembers;
int m_numDocMembers;
- Definition *m_parent;
+ const Definition *m_parent;
QCString m_docFile;
int m_docLine;
QList<ListItemInfo> *m_xrefListItems;
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 418b24a..94bb916 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -34,19 +34,12 @@
MemberList::MemberList() : m_listType(MemberListType_pubMethods)
{
+ //printf("%p: MemberList::MemberList()\n",this);
memberGroupList=0;
- m_varCnt=0;
- m_funcCnt=0;
- m_enumCnt=0;
- m_enumValCnt=0;
- m_typeCnt=0;
- m_seqCnt=0;
- m_dictCnt=0;
- m_protoCnt=0;
- m_defCnt=0;
- m_friendCnt=0;
m_numDecMembers=-1; // special value indicating that value needs to be computed
+ m_numDecEnumValues=0;
m_numDocMembers=-1; // special value indicating that value needs to be computed
+ m_numDocEnumValues=0;
m_inGroup=FALSE;
m_inFile=FALSE;
m_needsSorting=FALSE;
@@ -54,19 +47,12 @@ MemberList::MemberList() : m_listType(MemberListType_pubMethods)
MemberList::MemberList(MemberListType lt) : m_listType(lt)
{
+ //printf("%p: MemberList::MemberList(%d)\n",this,lt);
memberGroupList=0;
- m_varCnt=0;
- m_funcCnt=0;
- m_enumCnt=0;
- m_enumValCnt=0;
- m_typeCnt=0;
- m_seqCnt=0;
- m_dictCnt=0;
- m_protoCnt=0;
- m_defCnt=0;
- m_friendCnt=0;
m_numDecMembers=-1; // special value indicating that value needs to be computed
+ m_numDecEnumValues=0;
m_numDocMembers=-1; // special value indicating that value needs to be computed
+ m_numDocEnumValues=0;
m_inGroup=FALSE;
m_inFile=FALSE;
m_needsSorting=FALSE;
@@ -93,11 +79,11 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
return cmp!=0 ? cmp : c1->getDefLine()-c2->getDefLine();
}
-int MemberList::countInheritableMembers(ClassDef *inheritedFrom) const
+int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const
{
int count=0;
QListIterator<MemberDef> mli(*this);
- MemberDef *md;
+ const MemberDef *md;
for (mli.toFirst();(md=mli.current());++mli)
{
if (md->isBriefSectionVisible())
@@ -137,13 +123,15 @@ int MemberList::countInheritableMembers(ClassDef *inheritedFrom) const
/*! Count the number of members in this list that are visible in
* the declaration part of a compound's documentation page.
*/
-void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
+void MemberList::countDecMembers()
{
- if (m_numDecMembers!=-1) return;
-
+ if (m_numDecMembers!=-1) return;
+
//printf("----- countDecMembers count=%d ----\n",count());
+ /*
m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0;
m_typeCnt=m_seqCnt=m_dictCnt=m_protoCnt=m_defCnt=m_friendCnt=0;
+ */
m_numDecMembers=0;
QListIterator<MemberDef> mli(*this);
MemberDef *md;
@@ -156,7 +144,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
{
case MemberType_Variable: // fall through
case MemberType_Event: // fall through
- case MemberType_Property: m_varCnt++,m_numDecMembers++;
+ case MemberType_Property: /*m_varCnt++,*/
+ m_numDecMembers++;
break;
// apparently necessary to get this to show up in declarations section?
case MemberType_Interface: // fall through
@@ -165,23 +154,33 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
case MemberType_Signal: // fall through
case MemberType_DCOP: // fall through
case MemberType_Slot: if (!md->isRelated() || md->getClassDef())
- m_funcCnt++,m_numDecMembers++;
+ /*m_funcCnt++,*/
+ m_numDecMembers++;
+ break;
+ case MemberType_Enumeration: /*m_enumCnt++,*/
+ m_numDecMembers++;
+ break;
+ case MemberType_EnumValue: m_numDecEnumValues++;
+ m_numDecMembers++;
+ break;
+ case MemberType_Typedef: /*m_typeCnt++,*/
+ m_numDecMembers++;
break;
- case MemberType_Enumeration: m_enumCnt++,m_numDecMembers++; break;
- case MemberType_EnumValue: if (countEnumValues)
- m_enumValCnt++,m_numDecMembers++;
+ case MemberType_Sequence: /*m_seqCnt++,*/
+ m_numDecMembers++;
+ break;
+ case MemberType_Dictionary: /*m_dictCnt++,*/
+ m_numDecMembers++;
break;
- case MemberType_Typedef: m_typeCnt++,m_numDecMembers++; break;
- case MemberType_Sequence: m_seqCnt++,m_numDecMembers++; break;
- case MemberType_Dictionary: m_dictCnt++,m_numDecMembers++; break;
//case MemberType_Prototype: m_protoCnt++,m_numDecMembers++; break;
- case MemberType_Define: if (Config_getBool(EXTRACT_ALL) ||
- md->argsString() ||
+ case MemberType_Define: if (Config_getBool(EXTRACT_ALL) ||
+ md->argsString() ||
!md->initializer().isEmpty() ||
- md->hasDocumentation()
- ) m_defCnt++,m_numDecMembers++;
+ md->hasDocumentation()
+ ) /*m_defCnt++,*/ m_numDecMembers++;
break;
- case MemberType_Friend: m_friendCnt++,m_numDecMembers++;
+ case MemberType_Friend: /*m_friendCnt++,*/
+ m_numDecMembers++;
break;
default:
err("Unknown member type found for member `%s'\n!",md->name().data());
@@ -194,7 +193,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
{
- mg->countDecMembers(gd);
+ mg->countDecMembers();
+ /*
m_varCnt+=mg->varCount();
m_funcCnt+=mg->funcCount();
m_enumCnt+=mg->enumCount();
@@ -205,7 +205,9 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
m_protoCnt+=mg->protoCount();
m_defCnt+=mg->defineCount();
m_friendCnt+=mg->friendCount();
+ */
m_numDecMembers+=mg->numDecMembers();
+ m_numDecEnumValues+=mg->numDecEnumValues();
}
}
//printf("----- end countDecMembers ----\n");
@@ -213,7 +215,7 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd)
//printf("MemberList::countDecMembers()=%d\n",m_numDecMembers);
}
-void MemberList::countDocMembers(bool countEnumValues)
+void MemberList::countDocMembers()
{
if (m_numDocMembers!=-1) return; // used cached value
m_numDocMembers=0;
@@ -221,11 +223,14 @@ void MemberList::countDocMembers(bool countEnumValues)
MemberDef *md;
for (mli.toFirst();(md=mli.current());++mli)
{
- if (md->isDetailedSectionVisible(m_inGroup,m_inFile))
+ if (md->isDetailedSectionVisible(m_inGroup,m_inFile) && !md->isAlias())
{
// do not count enum values, since they do not produce entries of their own
- if (countEnumValues || md->memberType()!=MemberType_EnumValue)
- m_numDocMembers++;
+ if (md->memberType()==MemberType_EnumValue)
+ {
+ m_numDocEnumValues++;
+ }
+ m_numDocMembers++;
}
}
if (memberGroupList)
@@ -236,6 +241,7 @@ void MemberList::countDocMembers(bool countEnumValues)
{
mg->countDocMembers();
m_numDocMembers+=mg->numDocMembers();
+ m_numDocEnumValues+=mg->numDocEnumValues();
}
}
//printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList);
@@ -286,36 +292,74 @@ MemberListIterator::MemberListIterator(const MemberList &l) :
{
}
-int MemberList::countEnumValues(MemberDef *md,bool setAnonEnumType) const
+void MemberList::setAnonymousEnumType()
{
- int enumVars=0;
+ //printf("MemberList(%p)::setAnonymousEnumType()\n",this);
+ MemberListIterator mli(*this);
+ const MemberDef *md;
+ for ( ; (md=mli.current()); ++mli )
+ {
+ if (md->isBriefSectionVisible())
+ {
+ QCString name(md->name());
+ int i=name.findRev("::");
+ if (i!=-1) name=name.right(name.length()-i-2);
+ if (md->memberType()==MemberType_Enumeration && name[0]=='@')
+ {
+ const MemberList *mfl = md->enumFieldList();
+ if (mfl)
+ {
+ MemberListIterator vmli(*mfl);
+ MemberDef *vmd;
+ for ( ; (vmd=vmli.current()) ; ++vmli)
+ {
+ QCString vtype=vmd->typeString();
+ if ((vtype.find(name))!=-1)
+ {
+ vmd->setAnonymousEnumType(md);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (memberGroupList)
+ {
+ MemberGroupListIterator mgli(*memberGroupList);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->setAnonymousEnumType();
+ }
+ }
+}
+
+int MemberList::countEnumValues(const MemberDef *md) const
+{
+ int numEnumValues=0;
MemberListIterator vmli(*this);
- MemberDef *vmd;
+ const MemberDef *vmd;
QCString name(md->name());
int i=name.findRev("::");
- if (i!=-1) name=name.right(name.length()-i-2); // strip scope (TODO: is this needed?)
- if (name[0]=='@') // anonymous enum => append variables
+ if (i!=-1) name=name.right(name.length()-i-2);
+ if (name[0]=='@')
{
for ( ; (vmd=vmli.current()) ; ++vmli)
{
QCString vtype=vmd->typeString();
- if ((vtype.find(name))!=-1)
+ if ((vtype.find(name))!=-1)
{
- enumVars++;
- if (setAnonEnumType)
- {
- vmd->setAnonymousEnumType(md);
- }
+ numEnumValues++;
}
}
}
- return enumVars;
+ return numEnumValues;
}
bool MemberList::declVisible() const
{
MemberListIterator mli(*this);
- MemberDef *md;
+ const MemberDef *md;
for ( ; (md=mli.current()); ++mli )
{
if (md->isBriefSectionVisible())
@@ -340,7 +384,7 @@ bool MemberList::declVisible() const
{
// if this is an anonymous enum and there are variables of this
// enum type (i.e. enumVars>0), then we do not show the enum here.
- if (countEnumValues(md,FALSE)==0) // show enum here
+ if (countEnumValues(md)==0) // show enum here
{
return TRUE;
}
@@ -363,14 +407,18 @@ bool MemberList::declVisible() const
}
void MemberList::writePlainDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,
- GroupDef *gd,ClassDef *inheritedFrom,const char *inheritId
- )
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,
+ const GroupDef *gd,const ClassDef *inheritedFrom,const char *inheritId
+ ) const
{
//printf("----- writePlainDeclaration() ----\n");
static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
- countDecMembers();
- if (numDecMembers()==0)
+ if (numDecMembers()==-1)
+ {
+ err("MemberList::numDecMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n");
+ abort();
+ }
+ if (numDecMembers()<=numDecEnumValues())
{
//printf(" --> no members!\n");
return; // no members in this list
@@ -381,7 +429,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
ol.pushGeneratorState();
bool first=TRUE;
- MemberDef *md;
+ const MemberDef *md;
MemberListIterator mli(*this);
for ( ; (md=mli.current()); ++mli )
{
@@ -416,7 +464,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
{
// if this is an anonymous enum and there are variables of this
// enum type (i.e. enumVars>0), then we do not show the enum here.
- if (countEnumValues(md,TRUE)==0) // show enum here
+ if (countEnumValues(md)==0) // show enum here
{
//printf("Enum!!\n");
if (first)
@@ -549,9 +597,9 @@ void MemberList::writePlainDeclarations(OutputList &ol,
* @param lt Type of list that is inherited from.
*/
void MemberList::writeDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
const char *title,const char *subtitle, bool showEnumValues,
- bool showInline,ClassDef *inheritedFrom,MemberListType lt)
+ bool showInline,const ClassDef *inheritedFrom,MemberListType lt) const
{
(void)showEnumValues; // unused
@@ -559,8 +607,7 @@ void MemberList::writeDeclarations(OutputList &ol,
static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
QCString inheritId;
- countDecMembers(/*showEnumValues*/FALSE,gd); // count members shown in this section
- Definition *ctx = cd;
+ const Definition *ctx = cd;
if (ctx==0 && nd) ctx = nd;
if (ctx==0 && gd) ctx = gd;
if (ctx==0 && fd) ctx = fd;
@@ -569,6 +616,7 @@ void MemberList::writeDeclarations(OutputList &ol,
// this,title,subtitle,numDecMembers(),inheritedFrom);
int num = numDecMembers();
+ int numEnumValues = numDecEnumValues();
if (inheritedFrom)
{
//if ( cd && !optimizeVhdl && countInheritableMembers(inheritedFrom)>0 )
@@ -588,7 +636,7 @@ void MemberList::writeDeclarations(OutputList &ol,
ol.popGeneratorState();
}
}
- else if (num>0)
+ else if (num>numEnumValues)
{
if (title)
{
@@ -622,7 +670,7 @@ void MemberList::writeDeclarations(OutputList &ol,
}
}
}
- if (num>0)
+ if (num>numEnumValues)
{
// TODO: Two things need to be worked out for proper VHDL output:
// 1. Signals and types under the group need to be
@@ -685,13 +733,17 @@ void MemberList::writeDeclarations(OutputList &ol,
}
void MemberList::writeDocumentation(OutputList &ol,
- const char *scopeName, Definition *container,
- const char *title,bool showEnumValues,bool showInline)
+ const char *scopeName, const Definition *container,
+ const char *title,bool showEnumValues,bool showInline) const
{
- //printf("MemberList::writeDocumentation()\n");
+ if (numDocMembers()==-1)
+ {
+ err("MemberList::numDocMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n");
+ abort();
+ }
- countDocMembers(showEnumValues);
if (numDocMembers()==0) return;
+ if (!showEnumValues && numDocMembers()<=numDocEnumValues()) return;
if (title)
{
@@ -706,7 +758,7 @@ void MemberList::writeDocumentation(OutputList &ol,
ol.startMemberDocList();
MemberListIterator mli(*this);
- MemberDef *md;
+ const MemberDef *md;
// count the number of overloaded members
QDict<uint> overloadTotalDict(67);
@@ -758,20 +810,19 @@ void MemberList::writeDocumentation(OutputList &ol,
// members in a table
void MemberList::writeSimpleDocumentation(OutputList &ol,
- Definition *container)
+ const Definition *container) const
{
- countDocMembers(FALSE);
- //printf("MemberList count=%d\n",numDocMembers());
- if (numDocMembers()==0) return;
+ //printf("MemberList count=%d enumValues=%d\n",numDocMembers(),numDocEnumValues());
+ if (numDocMembers()<=numDocEnumValues()) return; // only enum values and they should be excluded
- ClassDef *cd = 0;
+ const ClassDef *cd = 0;
if (container && container->definitionType()==Definition::TypeClass)
{
- cd = dynamic_cast<ClassDef*>(container);
+ cd = dynamic_cast<const ClassDef*>(container);
}
ol.startMemberDocSimple(cd && cd->isJavaEnum());
MemberListIterator mli(*this);
- MemberDef *md;
+ const MemberDef *md;
for ( ; (md=mli.current()) ; ++mli)
{
md->writeMemberDocSimple(ol,container);
@@ -781,7 +832,7 @@ void MemberList::writeSimpleDocumentation(OutputList &ol,
// separate member pages
void MemberList::writeDocumentationPage(OutputList &ol,
- const char *scopeName, Definition *container)
+ const char *scopeName, const Definition *container) const
{
static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
@@ -791,7 +842,7 @@ void MemberList::writeDocumentationPage(OutputList &ol,
overloadTotalDict.setAutoDelete(TRUE);
overloadCountDict.setAutoDelete(TRUE);
MemberListIterator mli(*this);
- MemberDef *md;
+ const MemberDef *md;
for (mli.toFirst() ; (md=mli.current()) ; ++mli)
{
if (md->isDetailedSectionLinkable())
@@ -882,10 +933,10 @@ void MemberList::addListReferences(Definition *def)
MemberDef *md;
for ( ; (md=mli.current()) ; ++mli)
{
- if (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)
+ if (!md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup))
{
md->addListReference(def);
- MemberList *enumFields = md->enumFieldList();
+ const MemberList *enumFields = md->enumFieldList();
if (md->memberType()==MemberType_Enumeration && enumFields)
{
//printf(" Adding enum values!\n");
diff --git a/src/memberlist.h b/src/memberlist.h
index f0cc63d..3c227be 100644
--- a/src/memberlist.h
+++ b/src/memberlist.h
@@ -49,7 +49,7 @@ class MemberList : private QList<MemberDef>
MemberDef *getFirst() const;
MemberDef *take(uint index);
-
+/*
int varCount() const { ASSERT(m_numDecMembers!=-1); return m_varCnt; }
int funcCount() const { ASSERT(m_numDecMembers!=-1); return m_funcCnt; }
int enumCount() const { ASSERT(m_numDecMembers!=-1); return m_enumCnt; }
@@ -60,25 +60,29 @@ class MemberList : private QList<MemberDef>
int protoCount() const { ASSERT(m_numDecMembers!=-1); return m_protoCnt; }
int defineCount() const { ASSERT(m_numDecMembers!=-1); return m_defCnt; }
int friendCount() const { ASSERT(m_numDecMembers!=-1); return m_friendCnt; }
+*/
int numDecMembers() const { ASSERT(m_numDecMembers!=-1); return m_numDecMembers; }
+ int numDecEnumValues() const { return m_numDecEnumValues; }
int numDocMembers() const { ASSERT(m_numDocMembers!=-1); return m_numDocMembers; }
+ int numDocEnumValues() const { return m_numDocEnumValues; }
bool needsSorting() const { return m_needsSorting; }
- void countDecMembers(bool countEnumValues=FALSE,GroupDef *gd=0);
- void countDocMembers(bool countEnumValues=FALSE);
- int countInheritableMembers(ClassDef *inheritedFrom) const;
+ void countDecMembers();
+ void countDocMembers();
+ int countInheritableMembers(const ClassDef *inheritedFrom) const;
void writePlainDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd, GroupDef *gd,
- ClassDef *inheritedFrom,const char *inheritId);
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd,
+ const ClassDef *inheritedFrom,const char *inheritId) const;
void writeDeclarations(OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
const char *title,const char *subtitle,
bool showEnumValues=FALSE,bool showInline=FALSE,
- ClassDef *inheritedFrom=0,MemberListType lt=MemberListType_pubMethods);
+ const ClassDef *inheritedFrom=0,MemberListType lt=MemberListType_pubMethods) const;
void writeDocumentation(OutputList &ol,const char *scopeName,
- Definition *container,const char *title,bool showEnumValues=FALSE,bool showInline=FALSE);
- void writeSimpleDocumentation(OutputList &ol,Definition *container);
+ const Definition *container,const char *title,
+ bool showEnumValues=FALSE,bool showInline=FALSE) const;
+ void writeSimpleDocumentation(OutputList &ol,const Definition *container) const;
void writeDocumentationPage(OutputList &ol,
- const char *scopeName, Definition *container);
+ const char *scopeName, const Definition *container) const;
void writeTagFile(FTextStream &);
bool declVisible() const;
void addMemberGroup(MemberGroup *mg);
@@ -88,22 +92,26 @@ class MemberList : private QList<MemberDef>
void findSectionsInDocumentation();
void setNeedsSorting(bool b);
MemberGroupList *getMemberGroupList() const { return memberGroupList; }
+ void setAnonymousEnumType();
private:
int compareValues(const MemberDef *item1,const MemberDef *item2) const;
- int countEnumValues(MemberDef *md,bool setAnonEnumType) const;
+ int countEnumValues(const MemberDef *md) const;
+ /*
int m_varCnt;
int m_funcCnt;
int m_enumCnt;
- int m_enumValCnt;
int m_typeCnt;
int m_seqCnt;
int m_dictCnt;
int m_protoCnt;
int m_defCnt;
int m_friendCnt;
+ */
int m_numDecMembers; // number of members in the brief part of the memberlist
+ int m_numDecEnumValues;
int m_numDocMembers; // number of members in the detailed part of the memberlist
+ int m_numDocEnumValues;
MemberGroupList *memberGroupList;
bool m_inGroup; // is this list part of a group definition
bool m_inFile; // is this list part of a file definition
diff --git a/src/membername.cpp b/src/membername.cpp
index a5248c3..72809b3 100644
--- a/src/membername.cpp
+++ b/src/membername.cpp
@@ -32,10 +32,10 @@ MemberName::~MemberName()
int MemberName::compareValues(const MemberDef *m1, const MemberDef *m2) const
{
- ClassDef *c1=m1->getClassDef();
- ClassDef *c2=m2->getClassDef();
- FileDef *f1=m1->getFileDef();
- FileDef *f2=m2->getFileDef();
+ const ClassDef *c1=m1->getClassDef();
+ const ClassDef *c2=m2->getClassDef();
+ const FileDef *f1=m1->getFileDef();
+ const FileDef *f2=m2->getFileDef();
if (c1 && c2)
return qstrcmp(c1->name(),c2->name());
else if (f1 && f2)
@@ -52,10 +52,10 @@ MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>()
int MemberNameInfo::compareValues(const MemberInfo *m1,const MemberInfo *m2) const
{
- ClassDef *c1=m1->memberDef->getClassDef();
- ClassDef *c2=m2->memberDef->getClassDef();
- FileDef *f1=m1->memberDef->getFileDef();
- FileDef *f2=m2->memberDef->getFileDef();
+ const ClassDef *c1=m1->memberDef->getClassDef();
+ const ClassDef *c2=m2->memberDef->getClassDef();
+ const FileDef *f1=m1->memberDef->getFileDef();
+ const FileDef *f2=m2->memberDef->getFileDef();
if (c1 && c2)
return qstrcmp(c1->name(),c2->name());
else if (f1 && f2)
diff --git a/src/message.cpp b/src/message.cpp
index 2f3a06f..ddf757a 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -167,17 +167,29 @@ static void format_warn(const char *file,int line,const char *text)
static void do_warn(bool enabled, const char *file, int line, const char *prefix, const char *fmt, va_list args)
{
if (!enabled) return; // warning type disabled
- const int bufSize = 40960;
- char text[bufSize];
+
+ va_list argsCopy;
+ va_copy(argsCopy, args);
+
int l=0;
if (prefix)
{
- qstrncpy(text,prefix,bufSize);
l=strlen(prefix);
}
- vsnprintf(text+l, bufSize-l, fmt, args);
+ // determine needed buffersize based on:
+ // format + arguments
+ // prefix
+ // 1 position for `\0`
+ int bufSize = vsnprintf(NULL, 0, fmt, args) + l + 1;
+ char *text = (char *)malloc(sizeof(char) * bufSize);
+ if (prefix)
+ {
+ qstrncpy(text,prefix,bufSize);
+ }
+ vsnprintf(text+l, bufSize-l, fmt, argsCopy);
text[bufSize-1]='\0';
format_warn(file,line,text);
+ free(text);
}
void warn(const char *file,int line,const char *fmt, ...)
diff --git a/src/msc.cpp b/src/msc.cpp
index 29f96ac..0137e1b 100644
--- a/src/msc.cpp
+++ b/src/msc.cpp
@@ -24,6 +24,7 @@
#include "index.h"
#include "util.h"
#include "ftextstream.h"
+#include "mscgen_api.h"
#include <qdir.h>
@@ -97,50 +98,38 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir,
absOutFile+=portable_pathSeparator();
absOutFile+=outFile;
- // chdir to the output dir, so dot can find the font file.
- QCString oldDir = QDir::currentDirPath().utf8();
- // go to the html output directory (i.e. path)
- QDir::setCurrent(outDir);
- //printf("Going to dir %s\n",QDir::currentDirPath().data());
- QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension();
- QCString mscArgs;
- QCString imgName = outFile;
+ mscgen_format_t msc_format;
+ QCString imgName = absOutFile;
switch (format)
{
case MSC_BITMAP:
- mscArgs+="-T png";
+ msc_format = mscgen_format_png;
imgName+=".png";
break;
case MSC_EPS:
- mscArgs+="-T eps";
+ msc_format = mscgen_format_eps;
imgName+=".eps";
break;
case MSC_SVG:
- mscArgs+="-T svg";
+ msc_format = mscgen_format_svg;
imgName+=".svg";
break;
default:
- goto error; // I am not very fond of goto statements, but when in Rome...
+ return;
}
- mscArgs+=" -i \"";
- mscArgs+=inFile;
-
- mscArgs+="\" -o \"";
- mscArgs+=imgName+"\"";
- int exitCode;
-// printf("*** running: %s %s outDir:%s %s\n",mscExe.data(),mscArgs.data(),outDir,outFile);
- portable_sysTimerStart();
- if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0)
+ int code;
+ if ((code=mscgen_generate(inFile,imgName,msc_format))!=0)
{
- portable_sysTimerStop();
- goto error;
+ err("Problems generating msc output (error=%s). Look for typos in you msc file %s\n",
+ mscgen_error2str(code),inFile);
+ return;
}
- portable_sysTimerStop();
+
if ( (format==MSC_EPS) && (Config_getBool(USE_PDFLATEX)) )
{
QCString epstopdfArgs(maxCmdLine);
epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
- outFile,outFile);
+ absOutFile.data(),absOutFile.data());
portable_sysTimerStart();
if (portable_system("epstopdf",epstopdfArgs)!=0)
{
@@ -151,45 +140,28 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir,
Doxygen::indexList->addImageFile(imgName);
-error:
- QDir::setCurrent(oldDir);
}
-QCString getMscImageMapFromFile(const QCString& inFile, const QCString& outDir,
- const QCString& relPath,const QCString& context)
+static QCString getMscImageMapFromFile(const QCString& inFile, const QCString& outDir,
+ const QCString& relPath,const QCString& context,
+ bool writeSVGMap)
{
QCString outFile = inFile + ".map";
-
- //printf("*** running:getMscImageMapFromFile \n");
- // chdir to the output dir, so dot can find the font file.
- QCString oldDir = QDir::currentDirPath().utf8();
- // go to the html output directory (i.e. path)
- QDir::setCurrent(outDir);
- //printf("Going to dir %s\n",QDir::currentDirPath().data());
-
- QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension();
- QCString mscArgs = "-T ismap -i \"";
- mscArgs+=inFile;
- mscArgs+="\" -o \"";
- mscArgs+=outFile + "\"";
-
- int exitCode;
- portable_sysTimerStart();
- if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0)
+ int code;
+ if ((code=mscgen_generate(inFile,outFile,
+ writeSVGMap ? mscgen_format_svgmap : mscgen_format_pngmap))!=0)
{
- portable_sysTimerStop();
- QDir::setCurrent(oldDir);
+ err("Problems generating msc output (error=%s). Look for typos in you msc file %s\n",
+ mscgen_error2str(code),inFile.data());
return "";
}
- portable_sysTimerStop();
-
+
QGString result;
FTextStream tmpout(&result);
convertMapFile(tmpout, outFile, relPath, context);
QDir().remove(outFile);
- QDir::setCurrent(oldDir);
return result.data();
}
@@ -217,7 +189,7 @@ void writeMscImageMapFromFile(FTextStream &t,const QCString &inFile,
default:
t << "unknown";
}
- QCString imap = getMscImageMapFromFile(inFile,outDir,relPath,context);
+ QCString imap = getMscImageMapFromFile(inFile,outDir,relPath,context,format==MSC_SVG);
if (!imap.isEmpty())
{
t << "\" alt=\""
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
index 0740512..1e526ae 100644
--- a/src/namespacedef.cpp
+++ b/src/namespacedef.cpp
@@ -31,6 +31,7 @@
#include "membergroup.h"
#include "config.h"
#include "definitionimpl.h"
+#include "membername.h"
//------------------------------------------------------------------
@@ -48,17 +49,18 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef
virtual void insertUsedFile(FileDef *fd);
virtual void writeDocumentation(OutputList &ol);
virtual void writeMemberPages(OutputList &ol);
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const;
virtual void writeTagFile(FTextStream &);
- virtual void insertClass(ClassDef *cd);
- virtual void insertNamespace(NamespaceDef *nd);
+ virtual void insertClass(const ClassDef *cd);
+ virtual void insertNamespace(const NamespaceDef *nd);
virtual void insertMember(MemberDef *md);
virtual void computeAnchors();
- virtual int countMembers();
- virtual void addUsingDirective(NamespaceDef *nd);
- virtual NamespaceSDict *getUsedNamespaces() const;
- virtual void addUsingDeclaration(Definition *def);
- virtual SDict<Definition> *getUsedClasses() const { return usingDeclList; }
+ virtual void countMembers();
+ virtual int numDocMembers() const;
+ virtual void addUsingDirective(const NamespaceDef *nd);
+ virtual const NamespaceSDict *getUsedNamespaces() const;
+ virtual void addUsingDeclaration(const Definition *def);
+ virtual const SDict<Definition> *getUsedClasses() const { return usingDeclList; }
virtual void combineUsingRelations();
virtual QCString displayName(bool=TRUE) const;
virtual QCString localName() const;
@@ -75,7 +77,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef
virtual void findSectionsInDocumentation();
virtual void sortMemberLists();
virtual Definition *findInnerCompound(const char *name) const;
- virtual void addInnerCompound(Definition *d);
+ virtual void addInnerCompound(const Definition *d);
virtual void addListReferences();
virtual void setFileName(const QCString &fn);
virtual bool subGrouping() const { return m_subGrouping; }
@@ -87,7 +89,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef
virtual ClassSDict *getInterfaceSDict() const { return interfaceSDict; }
virtual ClassSDict *getStructSDict() const { return structSDict; }
virtual ClassSDict *getExceptionSDict() const { return exceptionSDict; }
- virtual NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; }
+ virtual const NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; }
virtual QCString title() const;
virtual QCString compoundTypeString() const;
@@ -108,21 +110,22 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef
void endMemberDeclarations(OutputList &ol);
void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d);
void writeInlineClasses(OutputList &ol);
- void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
- bool isConstantGroup=false);
void writeMemberGroups(OutputList &ol);
void writeAuthorSection(OutputList &ol);
void startMemberDocumentation(OutputList &ol);
void endMemberDocumentation(OutputList &ol);
- void writeSummaryLinks(OutputList &ol);
+ void writeSummaryLinks(OutputList &ol) const;
void addNamespaceAttributes(OutputList &ol);
void writeClassesToTagFile(FTextStream &,ClassSDict *d);
+ void writeNamespaceDeclarations(OutputList &ol,const QCString &title,
+ bool isConstantGroup=false);
+
QCString fileName;
FileList files;
NamespaceSDict *usingDirList;
- SDict<Definition> *usingDeclList;
+ SDict<Definition> *usingDeclList;
SDict<Definition> *m_innerCompounds;
MemberSDict *m_allMembersDict;
@@ -150,6 +153,109 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu
//------------------------------------------------------------------
+class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef
+{
+ public:
+ NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) : DefinitionAliasImpl(newScope,nd) {}
+ virtual ~NamespaceDefAliasImpl() {}
+ virtual DefType definitionType() const { return TypeNamespace; }
+
+ const NamespaceDef *getNSAlias() const { return dynamic_cast<const NamespaceDef*>(getAlias()); }
+
+ // ---- getters
+ virtual QCString getOutputFileBase() const
+ { return getNSAlias()->getOutputFileBase(); }
+ virtual QCString anchor() const
+ { return getNSAlias()->anchor(); }
+ virtual int numDocMembers() const
+ { return getNSAlias()->numDocMembers(); }
+ virtual void addUsingDirective(const NamespaceDef *nd) {}
+ virtual const NamespaceSDict *getUsedNamespaces() const
+ { return getNSAlias()->getUsedNamespaces(); }
+ virtual void addUsingDeclaration(const Definition *def) {}
+ virtual const SDict<Definition> *getUsedClasses() const
+ { return getNSAlias()->getUsedClasses(); }
+ virtual void combineUsingRelations() {}
+ virtual QCString displayName(bool b=TRUE) const
+ { return getNSAlias()->displayName(b); }
+ virtual QCString localName() const
+ { return getNSAlias()->localName(); }
+ virtual void setInline(bool isInline) { }
+ virtual bool isConstantGroup() const
+ { return getNSAlias()->isConstantGroup(); }
+ virtual bool isModule() const
+ { return getNSAlias()->isModule(); }
+ virtual bool isLibrary() const
+ { return getNSAlias()->isLibrary(); }
+ virtual bool isInline() const
+ { return getNSAlias()->isInline(); }
+ virtual bool isLinkableInProject() const
+ { return getNSAlias()->isLinkableInProject(); }
+ virtual bool isLinkable() const
+ { return getNSAlias()->isLinkable(); }
+ virtual bool hasDetailedDescription() const
+ { return getNSAlias()->hasDetailedDescription(); }
+ virtual Definition *findInnerCompound(const char *name) const
+ { return getNSAlias()->findInnerCompound(name); }
+ virtual bool subGrouping() const
+ { return getNSAlias()->subGrouping(); }
+ virtual MemberList *getMemberList(MemberListType lt) const
+ { return getNSAlias()->getMemberList(lt); }
+ virtual const QList<MemberList> &getMemberLists() const
+ { return getNSAlias()->getMemberLists(); }
+ virtual MemberDef *getMemberByName(const QCString &name) const
+ { return getNSAlias()->getMemberByName(name); }
+ virtual MemberGroupSDict *getMemberGroupSDict() const
+ { return getNSAlias()->getMemberGroupSDict(); }
+ virtual ClassSDict *getClassSDict() const
+ { return getNSAlias()->getClassSDict(); }
+ virtual ClassSDict *getInterfaceSDict() const
+ { return getNSAlias()->getInterfaceSDict(); }
+ virtual ClassSDict *getStructSDict() const
+ { return getNSAlias()->getStructSDict(); }
+ virtual ClassSDict *getExceptionSDict() const
+ { return getNSAlias()->getExceptionSDict(); }
+ virtual const NamespaceSDict *getNamespaceSDict() const
+ { return getNSAlias()->getNamespaceSDict(); }
+ virtual QCString title() const
+ { return getNSAlias()->title(); }
+ virtual QCString compoundTypeString() const
+ { return getNSAlias()->compoundTypeString(); }
+
+ // --- setters/actions
+ virtual void setMetaData(const QCString &m) {}
+ virtual void insertUsedFile(FileDef *fd) { }
+ virtual void writeDocumentation(OutputList &ol) {}
+ virtual void writeMemberPages(OutputList &ol) {}
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const {}
+ virtual void writeTagFile(FTextStream &) {}
+ virtual void insertClass(const ClassDef *cd) {}
+ virtual void insertNamespace(const NamespaceDef *nd) {}
+ virtual void insertMember(MemberDef *md) {}
+ virtual void computeAnchors() {}
+ virtual void countMembers() {}
+ virtual void addMembersToMemberGroup() {}
+ virtual void distributeMemberGroupDocumentation() {}
+ virtual void findSectionsInDocumentation() {}
+ virtual void sortMemberLists() {}
+ virtual void addInnerCompound(const Definition *d) {}
+ virtual void addListReferences() {}
+ virtual void setFileName(const QCString &fn) {}
+
+ void setVisited(bool v) { m_visited = v; }
+ bool isVisited() const { return m_visited; }
+
+ private:
+ bool m_visited;
+};
+
+NamespaceDef *createNamespaceDefAlias(const Definition *newScope,const NamespaceDef *nd)
+{
+ return new NamespaceDefAliasImpl(newScope,nd);
+}
+
+//------------------------------------------------------------------
+
NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc,
const char *name,const char *lref,
const char *fName, const char*type,
@@ -185,6 +291,7 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc,
memberGroupSDict = new MemberGroupSDict;
memberGroupSDict->setAutoDelete(TRUE);
m_visited=FALSE;
+ m_inline=FALSE;
m_subGrouping=Config_getBool(SUBGROUPING);
if (type && !strcmp("module", type))
{
@@ -272,20 +379,20 @@ void NamespaceDefImpl::insertUsedFile(FileDef *fd)
}
}
-void NamespaceDefImpl::addInnerCompound(Definition *d)
+void NamespaceDefImpl::addInnerCompound(const Definition *d)
{
m_innerCompounds->append(d->localName(),d);
if (d->definitionType()==Definition::TypeNamespace)
{
- insertNamespace(dynamic_cast<NamespaceDef *>(d));
+ insertNamespace(dynamic_cast<const NamespaceDef *>(d));
}
else if (d->definitionType()==Definition::TypeClass)
{
- insertClass(dynamic_cast<ClassDef *>(d));
+ insertClass(dynamic_cast<const ClassDef *>(d));
}
}
-void NamespaceDefImpl::insertClass(ClassDef *cd)
+void NamespaceDefImpl::insertClass(const ClassDef *cd)
{
ClassSDict *d = classSDict;
@@ -318,7 +425,7 @@ void NamespaceDefImpl::insertClass(ClassDef *cd)
}
}
-void NamespaceDefImpl::insertNamespace(NamespaceDef *nd)
+void NamespaceDefImpl::insertNamespace(const NamespaceDef *nd)
{
if (namespaceSDict->find(nd->name())==0)
{
@@ -360,6 +467,7 @@ void NamespaceDefImpl::addMembersToMemberGroup()
void NamespaceDefImpl::insertMember(MemberDef *md)
{
+ //printf("%s::insertMember(%s)\n",qPrint(name()),qPrint(md->name()));
if (md->isHidden()) return;
MemberList *allMemberList = getMemberList(MemberListType_allMembersList);
if (allMemberList==0)
@@ -415,6 +523,40 @@ void NamespaceDefImpl::insertMember(MemberDef *md)
md->getClassDef() ? md->getClassDef()->name().data() : "",
name().data());
}
+ // if this is an inline namespace, then insert an alias of this member in the outer scope.
+ if (isInline())
+ {
+ Definition *outerScope = getOuterScope();
+ if (outerScope)
+ {
+ MemberDef *aliasMd = 0;
+ if (outerScope->definitionType()==Definition::TypeNamespace)
+ {
+ aliasMd = createMemberDefAlias(outerScope,md);
+ dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd);
+ }
+ else if (outerScope->definitionType()==Definition::TypeFile)
+ {
+ aliasMd = createMemberDefAlias(outerScope,md);
+ dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd);
+ }
+ if (aliasMd)
+ {
+ MemberName *mn;
+ QCString name = md->name();
+ if ((mn=Doxygen::functionNameSDict->find(name)))
+ {
+ mn->append(aliasMd);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->append(aliasMd);
+ Doxygen::functionNameSDict->append(name,mn);
+ }
+ }
+ }
+ }
}
void NamespaceDefImpl::computeAnchors()
@@ -582,7 +724,7 @@ void NamespaceDefImpl::writeBriefDescription(OutputList &ol)
if (hasDetailedDescription())
{
ol.disableAllBut(OutputGenerator::Html);
- ol.startTextLink(0,"details");
+ ol.startTextLink(getOutputFileBase(),"details");
ol.parseText(theTranslator->trMore());
ol.endTextLink();
}
@@ -693,7 +835,7 @@ void NamespaceDefImpl::writeAuthorSection(OutputList &ol)
ol.popGeneratorState();
}
-void NamespaceDefImpl::writeSummaryLinks(OutputList &ol)
+void NamespaceDefImpl::writeSummaryLinks(OutputList &ol) const
{
ol.pushGeneratorState();
ol.disableAllBut(OutputGenerator::Html);
@@ -972,7 +1114,7 @@ void NamespaceDefImpl::writeMemberPages(OutputList &ol)
ol.popGeneratorState();
}
-void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const
+void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const
{
static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
@@ -1015,15 +1157,34 @@ void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd
ol.writeString(" </div>\n");
}
-int NamespaceDefImpl::countMembers()
+void NamespaceDefImpl::countMembers()
+{
+ QListIterator<MemberList> mli(m_memberLists);
+ MemberList *ml;
+ for (mli.toFirst();(ml=mli.current());++mli)
+ {
+ ml->countDecMembers();
+ ml->countDocMembers();
+ }
+ if (memberGroupSDict)
+ {
+ MemberGroupSDict::Iterator mgli(*memberGroupSDict);
+ MemberGroup *mg;
+ for (;(mg=mgli.current());++mgli)
+ {
+ mg->countDecMembers();
+ mg->countDocMembers();
+ }
+ }
+}
+
+int NamespaceDefImpl::numDocMembers() const
{
MemberList *allMemberList = getMemberList(MemberListType_allMembersList);
- if (allMemberList) allMemberList->countDocMembers();
- return (allMemberList ? allMemberList->numDocMembers() : 0) +
- classSDict->count() + interfaceSDict->count() + structSDict->count() + exceptionSDict->count();
+ return (allMemberList ? allMemberList->numDocMembers() : 0) + m_innerCompounds->count();
}
-void NamespaceDefImpl::addUsingDirective(NamespaceDef *nd)
+void NamespaceDefImpl::addUsingDirective(const NamespaceDef *nd)
{
if (usingDirList==0)
{
@@ -1036,13 +1197,13 @@ void NamespaceDefImpl::addUsingDirective(NamespaceDef *nd)
//printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count());
}
-NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const
+const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const
{
//printf("%p: NamespaceDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0);
return usingDirList;
}
-void NamespaceDefImpl::addUsingDeclaration(Definition *d)
+void NamespaceDefImpl::addUsingDeclaration(const Definition *d)
{
if (usingDeclList==0)
{
@@ -1297,14 +1458,10 @@ void NamespaceDefImpl::addMemberToList(MemberListType lt,MemberDef *md)
((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
ml->append(md);
-#if 0
- if (ml->needsSorting())
- ml->inSort(md);
- else
- ml->append(md);
-#endif
-
- if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml);
+ if (ml->listType()&MemberListType_declarationLists)
+ {
+ md->setSectionList(this,ml);
+ }
}
void NamespaceDefImpl::sortMemberLists()
diff --git a/src/namespacedef.h b/src/namespacedef.h
index bfa8c42..3be54f2 100644
--- a/src/namespacedef.h
+++ b/src/namespacedef.h
@@ -45,19 +45,20 @@ class NamespaceDef : virtual public Definition
virtual void writeDocumentation(OutputList &ol) = 0;
virtual void writeMemberPages(OutputList &ol) = 0;
- virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0;
+ virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0;
virtual void writeTagFile(FTextStream &) = 0;
- virtual void insertClass(ClassDef *cd) = 0;
- virtual void insertNamespace(NamespaceDef *nd) = 0;
- virtual void insertMember(MemberDef *md) = 0;
+ virtual void insertClass(const ClassDef *cd) = 0;
+ virtual void insertNamespace(const NamespaceDef *nd) = 0;
+ virtual void insertMember(MemberDef *md) = 0; // md cannot be const, since setSectionList is called on it
virtual void computeAnchors() = 0;
- virtual int countMembers() = 0;
- virtual void addUsingDirective(NamespaceDef *nd) = 0;
- virtual NamespaceSDict *getUsedNamespaces() const = 0;
- virtual void addUsingDeclaration(Definition *def) = 0;
- virtual SDict<Definition> *getUsedClasses() const = 0;
+ virtual void countMembers() = 0;
+ virtual int numDocMembers() const = 0;
+ virtual void addUsingDirective(const NamespaceDef *nd) = 0;
+ virtual const NamespaceSDict *getUsedNamespaces() const = 0;
+ virtual void addUsingDeclaration(const Definition *def) = 0;
+ virtual const SDict<Definition> *getUsedClasses() const = 0;
virtual void combineUsingRelations() = 0;
virtual QCString displayName(bool=TRUE) const = 0;
virtual QCString localName() const = 0;
@@ -77,7 +78,7 @@ class NamespaceDef : virtual public Definition
virtual void sortMemberLists() = 0;
virtual Definition *findInnerCompound(const char *name) const = 0;
- virtual void addInnerCompound(Definition *d) = 0;
+ virtual void addInnerCompound(const Definition *d) = 0;
virtual void addListReferences() = 0;
virtual void setFileName(const QCString &fn) = 0;
@@ -103,7 +104,7 @@ class NamespaceDef : virtual public Definition
virtual ClassSDict *getExceptionSDict() const = 0;
/*! Returns the namespaces contained in this namespace */
- virtual NamespaceSDict *getNamespaceSDict() const = 0;
+ virtual const NamespaceSDict *getNamespaceSDict() const = 0;
virtual QCString title() const = 0;
virtual QCString compoundTypeString() const = 0;
@@ -119,6 +120,9 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu
const char *refFile=0,const char*type=0,
bool isPublished=false);
+/** Factory method to create an alias of an existing namespace. Used for inline namespaces. */
+NamespaceDef *createNamespaceDefAlias(const Definition *newScope, const NamespaceDef *nd);
+
/** A list of NamespaceDef objects. */
class NamespaceList : public QList<NamespaceDef>
{
diff --git a/src/outputgen.h b/src/outputgen.h
index a99cff3..e302f42 100644
--- a/src/outputgen.h
+++ b/src/outputgen.h
@@ -124,7 +124,7 @@ class CodeOutputInterface
*/
virtual void writeCodeAnchor(const char *name) = 0;
- virtual void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile) = 0;
+ virtual void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) = 0;
virtual void addWord(const char *word,bool hiPriority) = 0;
};
@@ -346,7 +346,7 @@ class OutputGenerator : public BaseOutputDocInterface
//void setEncoding(const QCString &enc) { encoding = enc; }
//virtual void postProcess(QByteArray &) { }
- virtual void writeDoc(DocNode *,Definition *ctx,MemberDef *md) = 0;
+ virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md) = 0;
///////////////////////////////////////////////////////////////
// structural output interface
@@ -428,16 +428,16 @@ class OutputGenerator : public BaseOutputDocInterface
virtual void startClassDiagram() = 0;
virtual void endClassDiagram(const ClassDiagram &,const char *,const char *) = 0;
virtual void startDotGraph() = 0;
- virtual void endDotGraph(const DotClassGraph &g) = 0;
+ virtual void endDotGraph(DotClassGraph &g) = 0;
virtual void startInclDepGraph() = 0;
- virtual void endInclDepGraph(const DotInclDepGraph &g) = 0;
+ virtual void endInclDepGraph(DotInclDepGraph &g) = 0;
virtual void startGroupCollaboration() = 0;
- virtual void endGroupCollaboration(const DotGroupCollaboration &g) = 0;
+ virtual void endGroupCollaboration(DotGroupCollaboration &g) = 0;
virtual void startCallGraph() = 0;
- virtual void endCallGraph(const DotCallGraph &g) = 0;
+ virtual void endCallGraph(DotCallGraph &g) = 0;
virtual void startDirDepGraph() = 0;
- virtual void endDirDepGraph(const DotDirDeps &g) = 0;
- virtual void writeGraphicalHierarchy(const DotGfxHierarchyTable &g) = 0;
+ virtual void endDirDepGraph(DotDirDeps &g) = 0;
+ virtual void writeGraphicalHierarchy(DotGfxHierarchyTable &g) = 0;
virtual void startQuickIndices() = 0;
virtual void endQuickIndices() = 0;
virtual void writeSplitBar(const char *) = 0;
diff --git a/src/outputlist.cpp b/src/outputlist.cpp
index 93a1b6e..0306f94 100644
--- a/src/outputlist.cpp
+++ b/src/outputlist.cpp
@@ -129,7 +129,7 @@ void OutputList::popGeneratorState()
}
bool OutputList::generateDoc(const char *fileName,int startLine,
- Definition *ctx,MemberDef * md,
+ const Definition *ctx,const MemberDef * md,
const QCString &docStr,bool indexWords,
bool isExample,const char *exampleName,
bool singleLine,bool linkFromIndex)
@@ -159,7 +159,7 @@ bool OutputList::generateDoc(const char *fileName,int startLine,
return isEmpty;
}
-void OutputList::writeDoc(DocRoot *root,Definition *ctx,MemberDef *md)
+void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md)
{
QListIterator<OutputGenerator> it(m_outputs);
OutputGenerator *og;
@@ -316,12 +316,12 @@ void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5,a6,a7,a8),a
FORALL1(const char *a1,a1)
FORALL1(char a1,a1)
FORALL1(int a1,a1)
-FORALL1(const DotClassGraph &a1,a1)
-FORALL1(const DotInclDepGraph &a1,a1)
-FORALL1(const DotCallGraph &a1,a1)
-FORALL1(const DotDirDeps &a1,a1)
-FORALL1(const DotGfxHierarchyTable &a1,a1)
-FORALL1(const DotGroupCollaboration &a1,a1)
+FORALL1(DotClassGraph &a1,a1)
+FORALL1(DotInclDepGraph &a1,a1)
+FORALL1(DotCallGraph &a1,a1)
+FORALL1(DotDirDeps &a1,a1)
+FORALL1(DotGfxHierarchyTable &a1,a1)
+FORALL1(DotGroupCollaboration &a1,a1)
FORALL1(SectionTypes a1,a1)
#if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE)
FORALL1(bool a1,a1)
@@ -345,7 +345,7 @@ FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3)
FORALL3(const char *a1,int a2,const char *a3,a1,a2,a3)
FORALL3(const char *a1,const char *a2,SectionInfo::SectionType a3,a1,a2,a3)
FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3)
-FORALL3(Definition *a1,const char *a2,bool a3,a1,a2,a3)
+FORALL3(const Definition *a1,const char *a2,bool a3,a1,a2,a3)
FORALL4(SectionTypes a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4)
FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4)
FORALL4(const char *a1,const char *a2,const char *a3,int a4,a1,a2,a3,a4)
diff --git a/src/outputlist.h b/src/outputlist.h
index 5fd8017..35d68a8 100644
--- a/src/outputlist.h
+++ b/src/outputlist.h
@@ -75,10 +75,10 @@ class OutputList : public OutputDocInterface
//////////////////////////////////////////////////
bool generateDoc(const char *fileName,int startLine,
- Definition *ctx,MemberDef *md,const QCString &docStr,
+ const Definition *ctx,const MemberDef *md,const QCString &docStr,
bool indexWords,bool isExample,const char *exampleName=0,
bool singleLine=FALSE,bool linkFromIndex=FALSE);
- void writeDoc(DocRoot *root,Definition *ctx,MemberDef *md);
+ void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md);
bool parseText(const QCString &textStr);
@@ -391,25 +391,25 @@ class OutputList : public OutputDocInterface
{ forall(&OutputGenerator::endDescTableData); }
void startDotGraph()
{ forall(&OutputGenerator::startDotGraph); }
- void endDotGraph(const DotClassGraph &g)
+ void endDotGraph(DotClassGraph &g)
{ forall(&OutputGenerator::endDotGraph,g); }
void startInclDepGraph()
{ forall(&OutputGenerator::startInclDepGraph); }
- void endInclDepGraph(const DotInclDepGraph &g)
+ void endInclDepGraph(DotInclDepGraph &g)
{ forall(&OutputGenerator::endInclDepGraph,g); }
void startCallGraph()
{ forall(&OutputGenerator::startCallGraph); }
- void endCallGraph(const DotCallGraph &g)
+ void endCallGraph(DotCallGraph &g)
{ forall(&OutputGenerator::endCallGraph,g); }
void startDirDepGraph()
{ forall(&OutputGenerator::startDirDepGraph); }
- void endDirDepGraph(const DotDirDeps &g)
+ void endDirDepGraph(DotDirDeps &g)
{ forall(&OutputGenerator::endDirDepGraph,g); }
void startGroupCollaboration()
{ forall(&OutputGenerator::startGroupCollaboration); }
- void endGroupCollaboration(const DotGroupCollaboration &g)
+ void endGroupCollaboration(DotGroupCollaboration &g)
{ forall(&OutputGenerator::endGroupCollaboration,g); }
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &g)
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &g)
{ forall(&OutputGenerator::writeGraphicalHierarchy,g); }
void startTextBlock(bool dense=FALSE)
{ forall(&OutputGenerator::startTextBlock,dense); }
@@ -487,7 +487,7 @@ class OutputList : public OutputDocInterface
{ forall(&OutputGenerator::endFontClass); }
void writeCodeAnchor(const char *name)
{ forall(&OutputGenerator::writeCodeAnchor,name); }
- void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile)
+ void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile)
{ forall(&OutputGenerator::setCurrentDoc,context,anchor,isSourceFile); }
void addWord(const char *word,bool hiPriority)
{ forall(&OutputGenerator::addWord,word,hiPriority); }
@@ -520,12 +520,12 @@ class OutputList : public OutputDocInterface
FORALLPROTO1(char);
FORALLPROTO1(IndexSections);
FORALLPROTO1(int);
- FORALLPROTO1(const DotClassGraph &);
- FORALLPROTO1(const DotInclDepGraph &);
- FORALLPROTO1(const DotCallGraph &);
- FORALLPROTO1(const DotGroupCollaboration &);
- FORALLPROTO1(const DotDirDeps &);
- FORALLPROTO1(const DotGfxHierarchyTable &);
+ FORALLPROTO1(DotClassGraph &);
+ FORALLPROTO1(DotInclDepGraph &);
+ FORALLPROTO1(DotCallGraph &);
+ FORALLPROTO1(DotGroupCollaboration &);
+ FORALLPROTO1(DotDirDeps &);
+ FORALLPROTO1(DotGfxHierarchyTable &);
FORALLPROTO1(SectionTypes);
#if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE)
FORALLPROTO1(bool);
@@ -548,7 +548,7 @@ class OutputList : public OutputDocInterface
FORALLPROTO3(uchar,uchar,uchar);
FORALLPROTO3(const char *,const char *,const char *);
FORALLPROTO3(const ClassDiagram &,const char *,const char *);
- FORALLPROTO3(Definition*,const char *,bool);
+ FORALLPROTO3(const Definition*,const char *,bool);
FORALLPROTO4(SectionTypes,const char *,const char *,const char *);
FORALLPROTO4(const char *,const char *,const char *,const char *);
FORALLPROTO4(const char *,const char *,const char *,bool);
diff --git a/src/pagedef.cpp b/src/pagedef.cpp
index 8272cf6..9f11eb0 100644
--- a/src/pagedef.cpp
+++ b/src/pagedef.cpp
@@ -268,16 +268,16 @@ void PageDefImpl::writeDocumentation(OutputList &ol)
}
writePageDocumentation(ol);
+ ol.endContents();
ol.endPageDoc();
if (generateTreeView && getOuterScope()!=Doxygen::globalScope && !Config_getBool(DISABLE_INDEX))
{
- ol.endContents();
endFileWithNavPath(getOuterScope(),ol);
}
else
{
- endFile(ol);
+ endFile(ol,FALSE,TRUE);
}
ol.popGeneratorState();
diff --git a/src/parserintf.h b/src/parserintf.h
index 0942106..f03aac7 100644
--- a/src/parserintf.h
+++ b/src/parserintf.h
@@ -110,9 +110,9 @@ class ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
) = 0;
diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp
index 1ec4bf3..7a804b1 100644
--- a/src/perlmodgen.cpp
+++ b/src/perlmodgen.cpp
@@ -388,8 +388,6 @@ public:
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
@@ -1385,14 +1383,6 @@ void PerlModDocVisitor::visitPost(DocInternalRef *)
closeItem();
}
-void PerlModDocVisitor::visitPre(DocCopy *)
-{
-}
-
-void PerlModDocVisitor::visitPost(DocCopy *)
-{
-}
-
void PerlModDocVisitor::visitPre(DocText *)
{
}
@@ -1462,7 +1452,7 @@ static void addMemberTemplateLists(MemberDef *md,PerlModOutput &output)
}
#endif
-static void addTemplateList(ClassDef *cd,PerlModOutput &output)
+static void addTemplateList(const ClassDef *cd,PerlModOutput &output)
{
addTemplateArgumentList(cd->templateArguments(),output,cd->name());
}
@@ -1471,8 +1461,8 @@ static void addPerlModDocBlock(PerlModOutput &output,
const char *name,
const QCString &fileName,
int lineNr,
- Definition *scope,
- MemberDef *md,
+ const Definition *scope,
+ const MemberDef *md,
const QCString &text)
{
QCString stext = text.stripWhiteSpace();
@@ -1543,14 +1533,14 @@ public:
inline PerlModGenerator(bool pretty) : m_output(pretty) { }
- void generatePerlModForMember(MemberDef *md, Definition *);
- void generatePerlModSection(Definition *d, MemberList *ml,
+ void generatePerlModForMember(const MemberDef *md, const Definition *);
+ void generatePerlModSection(const Definition *d, MemberList *ml,
const char *name, const char *header=0);
- void addListOfAllMembers(ClassDef *cd);
- void generatePerlModForClass(ClassDef *cd);
- void generatePerlModForNamespace(NamespaceDef *nd);
- void generatePerlModForFile(FileDef *fd);
- void generatePerlModForGroup(GroupDef *gd);
+ void addListOfAllMembers(const ClassDef *cd);
+ void generatePerlModForClass(const ClassDef *cd);
+ void generatePerlModForNamespace(const NamespaceDef *nd);
+ void generatePerlModForFile(const FileDef *fd);
+ void generatePerlModForGroup(const GroupDef *gd);
void generatePerlModForPage(PageDef *pi);
bool createOutputFile(QFile &f, const char *s);
@@ -1567,7 +1557,7 @@ public:
void generate();
};
-void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
+void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Definition *)
{
// + declaration/definition arg lists
// + reimplements
@@ -1617,23 +1607,23 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
md->memberType()!=MemberType_Enumeration)
m_output.addFieldQuotedString("type", md->typeString());
- ArgumentList *al = md->argumentList();
+ const ArgumentList *al = md->argumentList();
if (isFunc) //function
{
m_output.addFieldBoolean("const", al!=0 && al->constSpecifier)
.addFieldBoolean("volatile", al!=0 && al->volatileSpecifier);
m_output.openList("parameters");
- ArgumentList *declAl = md->declArgumentList();
- ArgumentList *defAl = md->argumentList();
+ const ArgumentList *declAl = md->declArgumentList();
+ const ArgumentList *defAl = md->argumentList();
if (declAl && defAl && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
- Argument *a;
+ const Argument *a;
for (declAli.toFirst();(a=declAli.current());++declAli)
{
- Argument *defArg = defAli.current();
+ const Argument *defArg = defAli.current();
m_output.openHash();
if (!a->name.isEmpty())
@@ -1665,7 +1655,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
{
m_output.openList("parameters");
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
m_output.openHash()
@@ -1687,12 +1677,12 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
if (md->memberType()==MemberType_Enumeration) // enum
{
- MemberList *enumFields = md->enumFieldList();
+ const MemberList *enumFields = md->enumFieldList();
if (enumFields)
{
m_output.openList("values");
MemberListIterator emli(*enumFields);
- MemberDef *emd;
+ const MemberDef *emd;
for (emli.toFirst();(emd=emli.current());++emli)
{
m_output.openHash()
@@ -1711,7 +1701,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
}
}
- MemberDef *rmd = md->reimplements();
+ const MemberDef *rmd = md->reimplements();
if (rmd)
m_output.openHash("reimplements")
.addFieldQuotedString("name", rmd->name())
@@ -1732,7 +1722,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *)
m_output.closeHash();
}
-void PerlModGenerator::generatePerlModSection(Definition *d,
+void PerlModGenerator::generatePerlModSection(const Definition *d,
MemberList *ml,const char *name,const char *header)
{
if (ml==0) return; // empty list
@@ -1744,7 +1734,7 @@ void PerlModGenerator::generatePerlModSection(Definition *d,
m_output.openList("members");
MemberListIterator mli(*ml);
- MemberDef *md;
+ const MemberDef *md;
for (mli.toFirst();(md=mli.current());++mli)
{
generatePerlModForMember(md,d);
@@ -1753,7 +1743,7 @@ void PerlModGenerator::generatePerlModSection(Definition *d,
.closeHash();
}
-void PerlModGenerator::addListOfAllMembers(ClassDef *cd)
+void PerlModGenerator::addListOfAllMembers(const ClassDef *cd)
{
m_output.openList("all_members");
if (cd->memberNameInfoSDict())
@@ -1766,9 +1756,9 @@ void PerlModGenerator::addListOfAllMembers(ClassDef *cd)
MemberInfo *mi;
for (mii.toFirst();(mi=mii.current());++mii)
{
- MemberDef *md=mi->memberDef;
- ClassDef *cd=md->getClassDef();
- Definition *d=md->getGroupDef();
+ const MemberDef *md=mi->memberDef;
+ const ClassDef *cd=md->getClassDef();
+ const Definition *d=md->getGroupDef();
if (d==0) d = cd;
m_output.openHash()
@@ -1787,7 +1777,7 @@ void PerlModGenerator::addListOfAllMembers(ClassDef *cd)
m_output.closeList();
}
-void PerlModGenerator::generatePerlModForClass(ClassDef *cd)
+void PerlModGenerator::generatePerlModForClass(const ClassDef *cd)
{
// + brief description
// + detailed description
@@ -1845,7 +1835,7 @@ void PerlModGenerator::generatePerlModForClass(ClassDef *cd)
{
m_output.openList("inner");
ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
m_output.openHash()
.addFieldQuotedString("name", cd->name())
@@ -1937,7 +1927,7 @@ void PerlModGenerator::generatePerlModForClass(ClassDef *cd)
m_output.closeHash();
}
-void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
+void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd)
{
// + contained class definitions
// + contained namespace definitions
@@ -1958,7 +1948,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
{
m_output.openList("classes");
ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
m_output.openHash()
.addFieldQuotedString("name", cd->name())
@@ -1966,12 +1956,12 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
m_output.closeList();
}
- NamespaceSDict *nl = nd->getNamespaceSDict();
+ const NamespaceSDict *nl = nd->getNamespaceSDict();
if (nl)
{
m_output.openList("namespaces");
NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
m_output.openHash()
.addFieldQuotedString("name", nd->name())
@@ -1982,7 +1972,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
if (nd->getMemberGroupSDict())
{
MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
- MemberGroup *mg;
+ const MemberGroup *mg;
for (;(mg=mgli.current());++mgli)
generatePerlModSection(nd,mg->members(),"user-defined",mg->header());
}
@@ -2000,7 +1990,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd)
m_output.closeHash();
}
-void PerlModGenerator::generatePerlModForFile(FileDef *fd)
+void PerlModGenerator::generatePerlModForFile(const FileDef *fd)
{
// + includes files
// + includedby files
@@ -2069,7 +2059,7 @@ void PerlModGenerator::generatePerlModForFile(FileDef *fd)
m_output.closeHash();
}
-void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
+void PerlModGenerator::generatePerlModForGroup(const GroupDef *gd)
{
// + members
// + member groups
@@ -2094,7 +2084,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
{
m_output.openList("files");
QListIterator<FileDef> fli(*fl);
- FileDef *fd;
+ const FileDef *fd;
for (fli.toFirst();(fd=fli.current());++fli)
m_output.openHash()
.addFieldQuotedString("name", fd->name())
@@ -2107,7 +2097,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
{
m_output.openList("classes");
ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
m_output.openHash()
.addFieldQuotedString("name", cd->name())
@@ -2120,7 +2110,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
{
m_output.openList("namespaces");
NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
m_output.openHash()
.addFieldQuotedString("name", nd->name())
@@ -2146,7 +2136,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd)
{
m_output.openList("groups");
GroupListIterator gli(*gl);
- GroupDef *sgd;
+ const GroupDef *sgd;
for (gli.toFirst();(sgd=gli.current());++gli)
m_output.openHash()
.addFieldQuotedString("title", sgd->groupTitle())
@@ -2207,14 +2197,14 @@ bool PerlModGenerator::generatePerlModOutput()
m_output.openList("classes");
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
generatePerlModForClass(cd);
m_output.closeList();
m_output.openList("namespaces");
NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
generatePerlModForNamespace(nd);
m_output.closeList();
@@ -2225,7 +2215,7 @@ bool PerlModGenerator::generatePerlModOutput()
for (;(fn=fnli.current());++fnli)
{
FileNameIterator fni(*fn);
- FileDef *fd;
+ const FileDef *fd;
for (;(fd=fni.current());++fni)
generatePerlModForFile(fd);
}
@@ -2233,7 +2223,7 @@ bool PerlModGenerator::generatePerlModOutput()
m_output.openList("groups");
GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
+ const GroupDef *gd;
for (;(gd=gli.current());++gli)
{
generatePerlModForGroup(gd);
diff --git a/src/portable.cpp b/src/portable.cpp
index 3dccaed..3d64638 100644
--- a/src/portable.cpp
+++ b/src/portable.cpp
@@ -396,7 +396,7 @@ const char *portable_commandExtension()
bool portable_fileSystemIsCaseSensitive()
{
-#if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__)
+#if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__) || defined(__CYGWIN__)
return FALSE;
#else
return TRUE;
@@ -463,7 +463,18 @@ void portable_correct_path(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
const char *p = portable_getenv("PATH");
+ if (!p) return; // no path nothing to correct
QCString result = substitute(p,'/','\\');
if (result!=p) portable_setenv("PATH",result.data());
#endif
}
+
+void portable_unlink(const char *fileName)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ _unlink(fileName);
+#else
+ unlink(fileName);
+#endif
+}
+
diff --git a/src/portable.h b/src/portable.h
index c5578a3..83f90ef 100644
--- a/src/portable.h
+++ b/src/portable.h
@@ -23,6 +23,7 @@ void portable_unsetenv(const char *variable);
portable_off_t portable_fseek(FILE *f,portable_off_t offset, int whence);
portable_off_t portable_ftell(FILE *f);
FILE * portable_fopen(const char *fileName,const char *mode);
+void portable_unlink(const char *fileName);
char portable_pathSeparator();
char portable_pathListSeparator();
const char * portable_ghostScriptCommand();
diff --git a/src/pre.l b/src/pre.l
index 6ae379a..6829a92 100644
--- a/src/pre.l
+++ b/src/pre.l
@@ -73,9 +73,10 @@ struct CondCtx
struct FileState
{
- FileState(int size) : lineNr(1), fileBuf(size),
+ FileState(int size) : lineNr(1), curlyCount(0),fileBuf(size),
oldFileBuf(0), oldFileBufPos(0), bufState(0) {}
int lineNr;
+ int curlyCount;
BufStr fileBuf;
BufStr *oldFileBuf;
int oldFileBufPos;
@@ -1088,7 +1089,12 @@ static void expandExpression(QCString &expr,QCString *rest,int pos)
if (g_expandedDict->find(macroName)==0) // expand macro
{
Define *def=DefineManager::instance().isDefined(macroName);
- if (definedTest) // macro name was found after defined
+ if (macroName=="defined")
+ {
+ //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data());
+ definedTest=TRUE;
+ }
+ else if (definedTest) // macro name was found after defined
{
if (def) expMacro = " 1 "; else expMacro = " 0 ";
replaced=TRUE;
@@ -1117,11 +1123,6 @@ static void expandExpression(QCString &expr,QCString *rest,int pos)
replaced=replaceFunctionMacro(expr,rest,p+l,len,def,expMacro);
len+=l;
}
- else if (macroName=="defined")
- {
- //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data());
- definedTest=TRUE;
- }
if (replaced) // expand the macro and rescan the expression
{
@@ -1255,6 +1256,7 @@ QCString removeIdsAndMarkers(const char *s)
result+="0L";
p++;
while ((c=*p) && isId(c)) p++;
+ while ((c=*p) && isspace((uchar)c)) p++;
if (*p=='(') // undefined function macro
{
p++;
@@ -1605,6 +1607,8 @@ static void readIncludeFile(const QCString &inc)
fs->bufState = YY_CURRENT_BUFFER;
fs->lineNr = oldLineNr;
fs->fileName = oldFileName;
+ fs->curlyCount = g_curlyCount;
+ g_curlyCount = 0;
// push the state on the stack
g_includeStack.push(fs);
// set the scanner to the include file
@@ -2948,6 +2952,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'"))
//preYYin = fs->oldYYin;
g_inputBuf = fs->oldFileBuf;
g_inputBufPos = fs->oldFileBufPos;
+ g_curlyCount = fs->curlyCount;
setFileName(fs->fileName);
DBG_CTX((stderr,"######## FileName %s\n",g_yyFileName.data()));
diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h
index 26bb3e7..b4997fd 100644
--- a/src/printdocvisitor.h
+++ b/src/printdocvisitor.h
@@ -676,16 +676,6 @@ class PrintDocVisitor : public DocVisitor
indent_post();
printf("</internalref>\n");
}
- void visitPre(DocCopy *c)
- {
- indent_pre();
- printf("<copy link=\"%s\">\n",c->link().data());
- }
- void visitPost(DocCopy *)
- {
- indent_post();
- printf("</copy>\n");
- }
void visitPre(DocText *)
{
indent_pre();
diff --git a/src/pycode.h b/src/pycode.h
index 9817c39..de0a8a9 100644
--- a/src/pycode.h
+++ b/src/pycode.h
@@ -36,7 +36,7 @@ class Definition;
extern void parsePythonCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs);
extern void resetPythonCodeParserState();
diff --git a/src/pycode.l b/src/pycode.l
index 4fb27f1..010d188 100644
--- a/src/pycode.l
+++ b/src/pycode.l
@@ -63,7 +63,7 @@ static const char * g_inputString; //!< the code fragment as text
static int g_inputPosition; //!< read offset during parsing
static const char * g_currentFontClass;
static bool g_needsTermination;
-static Definition *g_searchCtx;
+static const Definition *g_searchCtx;
static bool g_collectXRefs;
static int g_inputLines; //!< number of line in the code fragment
static int g_yyLineNr; //!< current line number
@@ -162,7 +162,7 @@ void PyVariableContext::addVariable(const QCString &type,const QCString &name)
QCString lname = name.simplifyWhiteSpace();
Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast();
- ClassDef *varType;
+ const ClassDef *varType;
if (
(varType=g_codeClassSDict[ltype]) || // look for class definitions inside the code block
(varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions
@@ -212,7 +212,7 @@ class PyCallContext
Ctx() : name(g_name), type(g_type), cd(0) {}
QCString name;
QCString type;
- ClassDef *cd;
+ const ClassDef *cd;
};
PyCallContext()
@@ -223,7 +223,7 @@ class PyCallContext
virtual ~PyCallContext() {}
- void setClass(ClassDef *cd)
+ void setClass(const ClassDef *cd)
{
Ctx *ctx = m_classList.getLast();
if (ctx)
@@ -259,7 +259,7 @@ class PyCallContext
m_classList.append(new Ctx);
}
- ClassDef *getClass() const
+ const ClassDef *getClass() const
{
Ctx *ctx = m_classList.getLast();
@@ -320,7 +320,7 @@ static void addToSearchIndex(const char *text)
}
-static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
+static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
{
int pos=0;
QCString type = s;
@@ -330,7 +330,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition)
{
QCString clName=className+templSpec;
- ClassDef *cd=0;
+ const ClassDef *cd=0;
if (!g_classScope.isEmpty())
{
cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName);
@@ -437,7 +437,7 @@ static void nextCodeLine()
* split into multiple links with the same destination, one for each line.
*/
static void writeMultiLineCodeLink(CodeOutputInterface &ol,
- Definition *d,
+ const Definition *d,
const char *text)
{
static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
@@ -544,11 +544,11 @@ static bool getLinkInScope(const QCString &c, // scope
const char *text
)
{
- MemberDef *md;
- ClassDef *cd;
- FileDef *fd;
- NamespaceDef *nd;
- GroupDef *gd;
+ const MemberDef *md = 0;
+ const ClassDef *cd = 0;
+ const FileDef *fd = 0;
+ const NamespaceDef *nd = 0;
+ const GroupDef *gd = 0;
//printf("Trying `%s'::`%s'\n",c.data(),m.data());
if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) &&
md->isLinkable())
@@ -556,8 +556,8 @@ static bool getLinkInScope(const QCString &c, // scope
//Definition *d=0;
//if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
//printf("Found! d=%s\n",d?d->name().data():"<none>");
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable())
@@ -569,7 +569,7 @@ static bool getLinkInScope(const QCString &c, // scope
if (g_currentDefinition && g_currentMemberDef &&
md!=g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,md);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
}
//printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data());
@@ -616,8 +616,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data()));
- ClassDef *cd=0,*lcd=0; /** Class def that we may find */
- MemberDef *md=0; /** Member def that we may find */
+ const ClassDef *cd=0,*lcd=0; /** Class def that we may find */
+ const MemberDef *md=0; /** Member def that we may find */
//bool isLocal=FALSE;
if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable
@@ -634,7 +634,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
if (cd==0 && md==0) // also see if it is variable or enum or enum value
{
- NamespaceDef *nd = getResolvedNamespace(scope);
+ const NamespaceDef *nd = getResolvedNamespace(scope);
if (nd)
{
writeMultiLineCodeLink(ol,nd,clName);
@@ -663,13 +663,13 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
addToSearchIndex(className);
if (md)
{
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable() && md->isLinkable() &&
g_currentMemberDef && g_collectXRefs)
{
- addDocCrossReference(g_currentMemberDef,md);
+ addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md));
}
}
}
@@ -690,8 +690,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
writeMultiLineCodeLink(ol,md,clName);
addToSearchIndex(className);
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable() && md->isLinkable() &&
g_currentMemberDef && g_collectXRefs)
@@ -703,7 +703,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
}
else // check namespace as well
{
- NamespaceDef *mnd = getResolvedNamespace(scope);
+ const NamespaceDef *mnd = getResolvedNamespace(scope);
if (mnd)
{
MemberDef *md=mnd->getMemberByName(locName);
@@ -713,8 +713,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName,
g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope()));
writeMultiLineCodeLink(ol,md,clName);
addToSearchIndex(className);
- Definition *d = md->getOuterScope()==Doxygen::globalScope ?
- md->getBodyDef() : md->getOuterScope();
+ const Definition *d = md->getOuterScope()==Doxygen::globalScope ?
+ md->getBodyDef() : md->getOuterScope();
if (md->getGroupDef()) d = md->getGroupDef();
if (d && d->isLinkable() && md->isLinkable() &&
g_currentMemberDef && g_collectXRefs)
@@ -1091,7 +1091,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT
char *s=g_curClassBases.first();
while (s)
{
- ClassDef *baseDefToAdd=g_codeClassSDict[s];
+ const ClassDef *baseDefToAdd=g_codeClassSDict[s];
// Try to find class in global
// scope
@@ -1102,7 +1102,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT
if (baseDefToAdd && baseDefToAdd!=classDefToAdd)
{
- classDefToAdd->insertBaseClass(baseDefToAdd,s,Public,Normal);
+ classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal);
}
s=g_curClassBases.next();
@@ -1560,7 +1560,7 @@ static void adjustScopesAndSuites(unsigned indentLength)
void parsePythonCode(CodeOutputInterface &od,const char * /*className*/,
const QCString &s,bool exBlock, const char *exName,
FileDef *fd,int startLine,int endLine,bool inlineFragment,
- MemberDef *,bool,Definition *searchCtx,bool collectXRefs)
+ const MemberDef *,bool,const Definition *searchCtx,bool collectXRefs)
{
//printf("***parseCode()\n");
diff --git a/src/pyscanner.h b/src/pyscanner.h
index affa7ca..01235ee 100644
--- a/src/pyscanner.h
+++ b/src/pyscanner.h
@@ -53,9 +53,9 @@ class PythonLanguageScanner : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXrefs=TRUE
);
void resetCodeParserState();
diff --git a/src/pyscanner.l b/src/pyscanner.l
index 655b6e2..3f98f3a 100644
--- a/src/pyscanner.l
+++ b/src/pyscanner.l
@@ -143,7 +143,7 @@ static void initEntry()
current->stat = gstat;
current->lang = SrcLangExt_Python;
current->setParent(current_root);
- initGroupInfo(current);
+ Doxygen::docGroup.initGroupInfo(current);
gstat = FALSE;
}
@@ -537,6 +537,8 @@ STARTDOCSYMS "##"
%x SingleQuoteString
%x DoubleQuoteString
%x TripleString
+%x SingleQuoteStringIgnore
+%x DoubleQuoteStringIgnore
/* import */
%x FromMod
@@ -1282,8 +1284,28 @@ STARTDOCSYMS "##"
);
//Has base class-do stuff
}
+ "'" { // start of a single quoted string
+ g_stringContext=YY_START;
+ BEGIN( SingleQuoteStringIgnore );
+ }
+ "\"" { // start of a double quoted string
+ g_stringContext=YY_START;
+ BEGIN( DoubleQuoteStringIgnore );
+ }
}
+<SingleQuoteStringIgnore>{
+ "'" { // end of a single quoted string
+ BEGIN(g_stringContext);
+ }
+ . { }
+}
+<DoubleQuoteStringIgnore>{
+ "\"" { // end of a double quoted string
+ BEGIN(g_stringContext);
+ }
+ . { }
+}
<ClassCaptureIndent>{
"\n"|({BB}"\n") {
@@ -1702,6 +1724,10 @@ STARTDOCSYMS "##"
lineCount();
}
+<*>"'" {
+ fprintf(stderr,"Quote: %d\n",YY_START);
+ }
+
<*>. {
//printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n",
// yytext, YY_START, yyLineNr);
@@ -1746,14 +1772,14 @@ static void parseCompounds(Entry *rt)
current = new Entry;
initEntry();
- groupEnterCompound(yyFileName,yyLineNr,ce->name);
+ Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name);
pyscannerYYlex() ;
g_lexInit=TRUE;
delete current; current=0;
ce->program.resize(0);
- groupLeaveCompound(yyFileName,yyLineNr,ce->name);
+ Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name);
}
parseCompounds(ce);
@@ -1813,7 +1839,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
initParser();
current = new Entry;
- groupEnterFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.enterFile(yyFileName,yyLineNr);
current->reset();
initEntry();
@@ -1822,7 +1848,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt)
pyscannerYYlex();
g_lexInit=TRUE;
- groupLeaveFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.leaveFile(yyFileName,yyLineNr);
current_root->program.resize(0);
delete current; current=0;
@@ -1926,9 +1952,9 @@ void PythonLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
diff --git a/src/qhp.cpp b/src/qhp.cpp
index 6ce6b06..6260d09 100644
--- a/src/qhp.cpp
+++ b/src/qhp.cpp
@@ -193,7 +193,7 @@ void Qhp::addContentsItem(bool /*isDir*/, const char * name,
const char * /*ref*/, const char * file,
const char *anchor, bool /* separateIndex */,
bool /* addToNavIndex */,
- Definition * /*def*/)
+ const Definition * /*def*/)
{
//printf("Qhp::addContentsItem(%s) %d\n",name,m_sectionLevel);
// Backup difference before modification
@@ -214,7 +214,7 @@ void Qhp::addContentsItem(bool /*isDir*/, const char * name,
}
}
-void Qhp::addIndexItem(Definition *context,MemberDef *md,
+void Qhp::addIndexItem(const Definition *context,const MemberDef *md,
const char *sectionAnchor,const char *word)
{
(void)word;
diff --git a/src/qhp.h b/src/qhp.h
index 2c4e2c9..eba7db5 100644
--- a/src/qhp.h
+++ b/src/qhp.h
@@ -34,8 +34,8 @@ class Qhp : public IndexIntf
void addContentsItem(bool isDir, const char * name, const char * ref,
const char * file, const char * anchor,
bool separateIndex,bool addToNavIndex,
- Definition *def);
- void addIndexItem(Definition *context, MemberDef *md,
+ const Definition *def);
+ void addIndexItem(const Definition *context, const MemberDef *md,
const char *sectionAnchor, const char *title);
void addIndexFile(const char * name);
void addImageFile(const char * name);
diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp
index 55c03a5..4e89193 100644
--- a/src/rtfdocvisitor.cpp
+++ b/src/rtfdocvisitor.cpp
@@ -532,7 +532,9 @@ void RTFDocVisitor::visit(DocIncOperator *op)
//printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
// op->type(),op->isFirst(),op->isLast(),op->text().data());
DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
if (op->isFirst())
{
if (!m_hide)
@@ -549,14 +551,14 @@ void RTFDocVisitor::visit(DocIncOperator *op)
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(m_ci,op->context(),op->text(),langExt,
op->isExample(),op->exampleFile(),
fd, // fileDef
@@ -782,7 +784,6 @@ void RTFDocVisitor::visitPre(DocSimpleSect *s)
// special case 1: user defined title
if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
{
- m_t << ":";
m_t << "\\par";
m_t << "}"; // end bold
incIndentLevel();
@@ -1377,7 +1378,6 @@ void RTFDocVisitor::visitPre(DocParamSect *s)
default:
ASSERT(0);
}
- m_t << ":";
m_t << "\\par";
m_t << "}" << endl;
bool useTable = s->type()==DocParamSect::Param ||
@@ -1655,18 +1655,6 @@ void RTFDocVisitor::visitPost(DocInternalRef *)
m_t << " ";
}
-void RTFDocVisitor::visitPre(DocCopy *)
-{
- if (m_hide) return;
- DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCopy)}\n");
-}
-
-void RTFDocVisitor::visitPost(DocCopy *)
-{
- if (m_hide) return;
- DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocCopy)}\n");
-}
-
void RTFDocVisitor::visitPre(DocText *)
{
if (m_hide) return;
diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h
index b7cc3ea..82e4453 100644
--- a/src/rtfdocvisitor.h
+++ b/src/rtfdocvisitor.h
@@ -126,8 +126,6 @@ class RTFDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp
index bb69898..948d4cf 100644
--- a/src/rtfgen.cpp
+++ b/src/rtfgen.cpp
@@ -31,6 +31,10 @@
#include "diagram.h"
#include "language.h"
#include "dot.h"
+#include "dotcallgraph.h"
+#include "dotclassgraph.h"
+#include "dotdirdeps.h"
+#include "dotincldepgraph.h"
#include "version.h"
#include "pagedef.h"
#include "rtfstyle.h"
@@ -44,6 +48,8 @@
#include "filename.h"
#include "namespacedef.h"
+static bool DoxyCodeLineOpen = FALSE;
+
//#define DBG_RTF(x) x;
#define DBG_RTF(x)
@@ -1948,6 +1954,9 @@ void RTFGenerator::endCodeFragment()
//styleStack.pop();
//printf("RTFGenerator::endCodeFrament() top=%s\n",styleStack.top());
//t << rtf_Style_Reset << styleStack.top() << endl;
+ //endCodeLine checks is there is still an open code line, if so closes it.
+ endCodeLine();
+
DBG_RTF(t << "{\\comment (endCodeFragment) }" << endl)
t << "}" << endl;
m_omitParagraph = TRUE;
@@ -2497,7 +2506,7 @@ void RTFGenerator::startDotGraph()
DBG_RTF(t << "{\\comment (startDotGraph)}" << endl)
}
-void RTFGenerator::endDotGraph(const DotClassGraph &g)
+void RTFGenerator::endDotGraph(DotClassGraph &g)
{
newParagraph();
@@ -2521,7 +2530,7 @@ void RTFGenerator::startInclDepGraph()
DBG_RTF(t << "{\\comment (startInclDepGraph)}" << endl)
}
-void RTFGenerator::endInclDepGraph(const DotInclDepGraph &g)
+void RTFGenerator::endInclDepGraph(DotInclDepGraph &g)
{
newParagraph();
@@ -2543,7 +2552,7 @@ void RTFGenerator::startGroupCollaboration()
{
}
-void RTFGenerator::endGroupCollaboration(const DotGroupCollaboration &)
+void RTFGenerator::endGroupCollaboration(DotGroupCollaboration &)
{
}
@@ -2552,7 +2561,7 @@ void RTFGenerator::startCallGraph()
DBG_RTF(t << "{\\comment (startCallGraph)}" << endl)
}
-void RTFGenerator::endCallGraph(const DotCallGraph &g)
+void RTFGenerator::endCallGraph(DotCallGraph &g)
{
newParagraph();
@@ -2575,7 +2584,7 @@ void RTFGenerator::startDirDepGraph()
DBG_RTF(t << "{\\comment (startDirDepGraph)}" << endl)
}
-void RTFGenerator::endDirDepGraph(const DotDirDeps &g)
+void RTFGenerator::endDirDepGraph(DotDirDeps &g)
{
newParagraph();
@@ -2803,7 +2812,7 @@ void RTFGenerator::exceptionEntry(const char* prefix,bool closeBracket)
t << " ";
}
-void RTFGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
+void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *)
{
RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""));
n->accept(visitor);
@@ -3037,6 +3046,22 @@ void RTFGenerator::endInlineMemberDoc()
t << "\\cell }{\\row }" << endl;
}
+void RTFGenerator::writeLineNumber(const char *,const char *,const char *,int l)
+{
+ DoxyCodeLineOpen = TRUE;
+ t << QString("%1").arg(l,5) << " ";
+}
+void RTFGenerator::startCodeLine(bool)
+{
+ DoxyCodeLineOpen = TRUE;
+ col=0;
+}
+void RTFGenerator::endCodeLine()
+{
+ if (DoxyCodeLineOpen) lineBreak();
+ DoxyCodeLineOpen = FALSE;
+}
+
void RTFGenerator::startLabels()
{
}
diff --git a/src/rtfgen.h b/src/rtfgen.h
index b6b32c7..b5f06f0 100644
--- a/src/rtfgen.h
+++ b/src/rtfgen.h
@@ -41,7 +41,7 @@ class RTFGenerator : public OutputGenerator
bool isEnabled(OutputType o) { return (o==RTF && active); }
OutputGenerator *get(OutputType o) { return (o==RTF) ? this : 0; }
- void writeDoc(DocNode *,Definition *,MemberDef *);
+ void writeDoc(DocNode *,const Definition *,const MemberDef *);
void startFile(const char *name,const char *manName,const char *title);
void writeSearchInfo() {}
@@ -127,9 +127,9 @@ class RTFGenerator : public OutputGenerator
void writeAnchor(const char *fileName,const char *name);
void startCodeFragment();
void endCodeFragment();
- void writeLineNumber(const char *,const char *,const char *,int l) { t << QString("%1").arg(l,5) << " "; }
- void startCodeLine(bool) { col=0; }
- void endCodeLine() { lineBreak(); }
+ void writeLineNumber(const char *,const char *,const char *,int l);
+ void startCodeLine(bool);
+ void endCodeLine();
void startEmphasis() { t << "{\\i "; }
void endEmphasis() { t << "}"; }
void startBold() { t << "{\\b "; }
@@ -202,16 +202,16 @@ class RTFGenerator : public OutputGenerator
void endDescTableData();
void startDotGraph();
- void endDotGraph(const DotClassGraph &);
+ void endDotGraph(DotClassGraph &);
void startInclDepGraph();
- void endInclDepGraph(const DotInclDepGraph &);
+ void endInclDepGraph(DotInclDepGraph &);
void startGroupCollaboration();
- void endGroupCollaboration(const DotGroupCollaboration &g);
+ void endGroupCollaboration(DotGroupCollaboration &g);
void startCallGraph();
- void endCallGraph(const DotCallGraph &);
+ void endCallGraph(DotCallGraph &);
void startDirDepGraph();
- void endDirDepGraph(const DotDirDeps &g);
- void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {}
+ void endDirDepGraph(DotDirDeps &g);
+ void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
void startMemberGroupHeader(bool);
void endMemberGroupHeader();
@@ -262,7 +262,7 @@ class RTFGenerator : public OutputGenerator
void endFontClass();
void writeCodeAnchor(const char *) {}
- void setCurrentDoc(Definition *,const char *,bool) {}
+ void setCurrentDoc(const Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
static bool preProcessFileInplace(const char *path,const char *name);
diff --git a/src/scanner.h b/src/scanner.h
index ac574e2..c0d3dff 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -48,9 +48,9 @@ class CLanguageScanner : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
void resetCodeParserState();
diff --git a/src/scanner.l b/src/scanner.l
index 3d3c109..5ecf261 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -78,6 +78,7 @@ static int lastHereDocContext;
static int lastDefineContext;
static int lastAlignAsContext;
static int lastC11AttributeContext;
+static int lastModifierContext;
static Protection protection;
static Protection baseProt;
static int sharpCount = 0 ;
@@ -246,7 +247,7 @@ static void initEntry()
// //printf("Appending group %s\n",autoGroupStack.top()->groupname.data());
// current->groups->append(new Grouping(*autoGroupStack.top()));
//}
- initGroupInfo(current);
+ Doxygen::docGroup.initGroupInfo(current);
isTypedef=FALSE;
}
@@ -766,6 +767,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
/** Slice states */
+%x SliceOptional
%x SliceMetadata
%x SliceSequence
%x SliceSequenceName
@@ -1390,6 +1392,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
current->explicitExternal = TRUE;
lineCount();
}
+<FindMembers>{B}*"const"{BN}+ { current->type += " const ";
+ if (insideCS) current->stat = TRUE;
+ lineCount();
+ }
<FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual ";
current->virt = Virtual;
lineCount();
@@ -2435,6 +2441,19 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
current->type+=yytext;
BEGIN(DeclType);
}
+ else if (insideSlice && qstrcmp(yytext,"optional")==0)
+ {
+ if (current->type.isEmpty())
+ {
+ current->type = "optional";
+ }
+ else
+ {
+ current->type += " optional";
+ }
+ lastModifierContext = YY_START;
+ BEGIN(SliceOptional);
+ }
else
{
if (YY_START==FindMembers)
@@ -2830,17 +2849,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
}
-<FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") {
+<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") {
//handleGroupStartCommand(current->name);
if (previous && previous->section==Entry::GROUPDOC_SEC)
{
// link open command to the group defined in the previous entry
- openGroup(previous,yyFileName,yyLineNr);
+ Doxygen::docGroup.open(previous,yyFileName,yyLineNr);
}
else
{
// link open command to the current entry
- openGroup(current,yyFileName,yyLineNr);
+ Doxygen::docGroup.open(current,yyFileName,yyLineNr);
}
//current = tmp;
initEntry();
@@ -2882,9 +2901,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
}
}
}
-<FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}"[^*]*"*/" {
+<FindMembers,FindFields,ReadInitializer>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" {
bool insideEnum = YY_START==FindFields || (YY_START==ReadInitializer && lastInitializerContext==FindFields); // see bug746226
- closeGroup(current,yyFileName,yyLineNr,insideEnum);
+ Doxygen::docGroup.close(current,yyFileName,yyLineNr,insideEnum);
}
<FindMembers>"=" { // in PHP code this could also be due to "<?="
current->bodyLine = yyLineNr;
@@ -3589,6 +3608,20 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
BEGIN (lastSquareContext);
}
}
+<SliceOptional>"(" {
+ current->type += "(";
+ roundCount++;
+ }
+<SliceOptional>[0-9]+ {
+ current->type += yytext;
+ }
+<SliceOptional>")" {
+ current->type += ")";
+ if(--roundCount<=0)
+ {
+ BEGIN (lastModifierContext);
+ }
+ }
<IDLAttribute>"]" {
// end of IDL function attribute
if (--squareCount<=0)
@@ -3941,6 +3974,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
else
{
current->endBodyLine = yyLineNr;
+ Entry * original_root = current_root; // save root this namespace is in
if (current->section == Entry::NAMESPACE_SEC && current->type == "namespace")
{
int split_point;
@@ -4005,6 +4039,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
)
{ // namespaces and interfaces and java classes ends with a closing bracket without semicolon
current->reset();
+ current_root = original_root; // restore scope from before namespace descent
initEntry();
memspecEntry = 0;
BEGIN( FindMembers ) ;
@@ -4625,7 +4660,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
unput(lastCopyArgChar);
BEGIN( lastCommentInArgContext );
}
-<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
+<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
docBlockName=&yytext[1];
fullArgString+=yytext;
BEGIN(CopyArgVerbatim);
@@ -4643,7 +4678,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
fullArgString+=yytext;
BEGIN(CopyArgVerbatim);
}
-<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9] { // end of verbatim block
+<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9\-] { // end of verbatim block
fullArgString+=yytext;
if (yytext[1]=='f') // end of formula
{
@@ -6252,6 +6287,43 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
startCommentBlock(FALSE);
BEGIN( DocBlock );
}
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>"/**"[*]+{BL} {
+
+ static bool javadocBanner = Config_getBool(JAVADOC_BANNER);
+
+ if( javadocBanner ) {
+ lastDocContext = YY_START;
+
+ //printf("Found comment banner at %s:%d\n",yyFileName,yyLineNr);
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->inside = current_root->name+"::";
+ }
+ current->docLine = yyLineNr;
+ current->docFile = yyFileName;
+ docBlockContext = YY_START;
+ docBlockInBody = YY_START==SkipCurly;
+ static bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF);
+ docBlockAutoBrief = javadocAutoBrief;
+
+ QCString indent;
+ indent.fill(' ',computeIndent(yytext,g_column));
+ docBlock=indent;
+
+ if (docBlockAutoBrief)
+ {
+ current->briefLine = yyLineNr;
+ current->briefFile = yyFileName;
+ }
+ startCommentBlock(FALSE);
+ BEGIN( DocBlock );
+ } else {
+ current->program += yytext ;
+ lastContext = YY_START ;
+ BEGIN( Comment ) ;
+ }
+
+ }
<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] {
removeSlashes=(yytext[1]=='/');
lastDocContext = YY_START;
@@ -6563,7 +6635,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP})
g_nestedComment=FALSE;
BEGIN(DocCopyBlock);
}
-<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!)
+<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!)
docBlock+=yytext;
docBlockName=&yytext[1];
g_fencedSize=0;
@@ -7135,13 +7207,13 @@ static void parseCompounds(Entry *rt)
//memberGroupId = DOX_NOGROUP;
//memberGroupRelates.resize(0);
//memberGroupInside.resize(0);
- groupEnterCompound(yyFileName,yyLineNr,ce->name);
+ Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name);
scannerYYlex() ;
g_lexInit=TRUE;
//forceEndGroup();
- groupLeaveCompound(yyFileName,yyLineNr,ce->name);
+ Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name);
delete current; current=0;
ce->program.resize(0);
@@ -7201,7 +7273,7 @@ static void parseMain(const char *fileName,
current_root = rt ;
initParser();
- groupEnterFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.enterFile(yyFileName,yyLineNr);
current = new Entry;
//printf("current=%p current_root=%p\n",current,current_root);
int sec=guessSection(yyFileName);
@@ -7233,7 +7305,7 @@ static void parseMain(const char *fileName,
}
//forceEndGroup();
- groupLeaveFile(yyFileName,yyLineNr);
+ Doxygen::docGroup.leaveFile(yyFileName,yyLineNr);
//if (depthIf>0)
//{
@@ -7368,9 +7440,9 @@ void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
diff --git a/src/searchindex.cpp b/src/searchindex.cpp
index c9f8ec1..b21d587 100644
--- a/src/searchindex.cpp
+++ b/src/searchindex.cpp
@@ -86,12 +86,12 @@ SearchIndex::SearchIndex() : SearchIndexIntf(Internal),
for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>);
}
-void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
+void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile)
{
if (ctx==0) return;
assert(!isSourceFile || ctx->definitionType()==Definition::TypeFile);
//printf("SearchIndex::setCurrentDoc(%s,%s,%s)\n",name,baseName,anchor);
- QCString url=isSourceFile ? (dynamic_cast<FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase();
+ QCString url=isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase();
url+=Config_getString(HTML_FILE_EXTENSION);
QCString baseUrl = url;
if (anchor) url+=QCString("#")+anchor;
@@ -99,7 +99,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource
QCString name=ctx->qualifiedName();
if (ctx->definitionType()==Definition::TypeMember)
{
- MemberDef *md = dynamic_cast<MemberDef *>(ctx);
+ const MemberDef *md = dynamic_cast<const MemberDef *>(ctx);
name.prepend((md->getLanguage()==SrcLangExt_Fortran ?
theTranslator->trSubprogram(TRUE,TRUE) :
theTranslator->trMember(TRUE,TRUE))+" ");
@@ -116,7 +116,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource
{
case Definition::TypePage:
{
- PageDef *pd = dynamic_cast<PageDef *>(ctx);
+ const PageDef *pd = dynamic_cast<const PageDef *>(ctx);
if (pd->hasTitle())
{
name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title();
@@ -129,7 +129,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource
break;
case Definition::TypeClass:
{
- ClassDef *cd = dynamic_cast<ClassDef *>(ctx);
+ const ClassDef *cd = dynamic_cast<const ClassDef *>(ctx);
name.prepend(cd->compoundTypeString()+" ");
}
break;
@@ -151,7 +151,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource
break;
case Definition::TypeGroup:
{
- GroupDef *gd = dynamic_cast<GroupDef *>(ctx);
+ const GroupDef *gd = dynamic_cast<const GroupDef *>(ctx);
if (gd->groupTitle())
{
name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle();
@@ -442,11 +442,11 @@ SearchIndexExternal::~SearchIndexExternal()
delete p;
}
-static QCString definitionToName(Definition *ctx)
+static QCString definitionToName(const Definition *ctx)
{
if (ctx && ctx->definitionType()==Definition::TypeMember)
{
- MemberDef *md = dynamic_cast<MemberDef*>(ctx);
+ const MemberDef *md = dynamic_cast<const MemberDef*>(ctx);
if (md->isFunction())
return "function";
else if (md->isSlot())
@@ -477,7 +477,7 @@ static QCString definitionToName(Definition *ctx)
switch(ctx->definitionType())
{
case Definition::TypeClass:
- return (dynamic_cast<ClassDef*>(ctx))->compoundTypeString();
+ return (dynamic_cast<const ClassDef*>(ctx))->compoundTypeString();
case Definition::TypeFile:
return "file";
case Definition::TypeNamespace:
@@ -497,10 +497,10 @@ static QCString definitionToName(Definition *ctx)
return "unknown";
}
-void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile)
+void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile)
{
QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID));
- QCString baseName = isSourceFile ? (dynamic_cast<FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase();
+ QCString baseName = isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase();
QCString url = baseName + Doxygen::htmlFileExtension;
if (anchor) url+=QCString("#")+anchor;
QCString key = extId+";"+url;
@@ -514,7 +514,7 @@ void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool
e->name = ctx->qualifiedName();
if (ctx->definitionType()==Definition::TypeMember)
{
- e->args = (dynamic_cast<MemberDef*>(ctx))->argsString();
+ e->args = (dynamic_cast<const MemberDef*>(ctx))->argsString();
}
e->extId = extId;
e->url = url;
@@ -585,14 +585,14 @@ void SearchIndexExternal::write(const char *fileName)
static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES];
-static void addMemberToSearchIndex(MemberDef *md)
+static void addMemberToSearchIndex(const MemberDef *md)
{
static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
bool isLinkable = md->isLinkable();
- ClassDef *cd=0;
- NamespaceDef *nd=0;
- FileDef *fd=0;
- GroupDef *gd=0;
+ const ClassDef *cd=0;
+ const NamespaceDef *nd=0;
+ const FileDef *fd=0;
+ const GroupDef *gd=0;
if (isLinkable &&
(
((cd=md->getClassDef()) && cd->isLinkable() && cd->templateMaster()==0) ||
@@ -956,6 +956,7 @@ void createJavascriptSearchIndex()
void writeJavascriptSearchIndex()
{
int i;
+ int cnt = 0;
// write index files
QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search";
@@ -1043,7 +1044,7 @@ void writeJavascriptSearchIndex()
}
firstEntry=FALSE;
- ti << " ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',[";
+ ti << " ['" << dl->id() << "_" << cnt++ << "',['" << convertToXML(dl->name()) << "',[";
if (dl->count()==1) // item with a unique name
{
@@ -1074,7 +1075,7 @@ void writeJavascriptSearchIndex()
}
else if (md)
{
- FileDef *fd = md->getBodyDef();
+ const FileDef *fd = md->getBodyDef();
if (fd==0) fd = md->getFileDef();
if (fd)
{
@@ -1155,8 +1156,8 @@ void writeJavascriptSearchIndex()
{
if (md)
{
- FileDef *fd = md->getBodyDef();
- if (fd==0) fd = md->getFileDef();
+ const FileDef *fd = md->getBodyDef();
+ if (fd==0) fd = md->resolveAlias()->getFileDef();
if (fd)
{
if (!prefix.isEmpty()) prefix+=":&#160;";
@@ -1165,7 +1166,7 @@ void writeJavascriptSearchIndex()
}
}
}
- else if (md && (md->getClassDef() || md->getNamespaceDef()))
+ else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef()))
// member in class or namespace scope
{
SrcLangExt lang = md->getLanguage();
@@ -1315,7 +1316,7 @@ SearchIndexList::~SearchIndexList()
{
}
-void SearchIndexList::append(Definition *d)
+void SearchIndexList::append(const Definition *d)
{
QCString dispName = d->localName();
SearchDefinitionList *l = find(dispName);
@@ -1323,11 +1324,11 @@ void SearchIndexList::append(Definition *d)
{
if (d->definitionType()==Definition::TypeGroup)
{
- dispName = (dynamic_cast<GroupDef*>(d))->groupTitle();
+ dispName = (dynamic_cast<const GroupDef*>(d))->groupTitle();
}
else if (d->definitionType()==Definition::TypePage)
{
- dispName = (dynamic_cast<PageDef*>(d))->title();
+ dispName = (dynamic_cast<const PageDef*>(d))->title();
}
l=new SearchDefinitionList(searchId(dispName),dispName);
SDict< SearchDefinitionList >::append(dispName,l);
diff --git a/src/searchindex.h b/src/searchindex.h
index 0345b41..9a612ad 100644
--- a/src/searchindex.h
+++ b/src/searchindex.h
@@ -72,7 +72,7 @@ class SearchIndexIntf
enum Kind { Internal, External };
SearchIndexIntf(Kind k) : m_kind(k) {}
virtual ~SearchIndexIntf() {}
- virtual void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile) = 0;
+ virtual void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) = 0;
virtual void addWord(const char *word,bool hiPriority) = 0;
virtual void write(const char *file) = 0;
Kind kind() const { return m_kind; }
@@ -84,7 +84,7 @@ class SearchIndex : public SearchIndexIntf
{
public:
SearchIndex();
- void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile);
+ void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile);
void addWord(const char *word,bool hiPriority);
void write(const char *file);
private:
@@ -103,7 +103,7 @@ class SearchIndexExternal : public SearchIndexIntf
public:
SearchIndexExternal();
~SearchIndexExternal();
- void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile);
+ void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile);
void addWord(const char *word,bool hiPriority);
void write(const char *file);
private:
@@ -148,10 +148,10 @@ class SearchDefinitionList : public QList<Definition>
class SearchIndexList : public SDict< SearchDefinitionList >
{
public:
- typedef Definition ElementType;
+ typedef const Definition ElementType;
SearchIndexList(uint letter);
~SearchIndexList();
- void append(Definition *d);
+ void append(const Definition *d);
uint letter() const;
private:
int compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const;
diff --git a/src/sqlcode.h b/src/sqlcode.h
index 9c1f7e0..d8a09b7 100644
--- a/src/sqlcode.h
+++ b/src/sqlcode.h
@@ -30,7 +30,7 @@ class Definition;
extern void parseSqlCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs);
extern void resetSqlCodeParserState();
diff --git a/src/sqlcode.l b/src/sqlcode.l
index 5e45083..eec9732 100644
--- a/src/sqlcode.l
+++ b/src/sqlcode.l
@@ -15,6 +15,10 @@
%option never-interactive
%option prefix="sqlcodeYY"
+%option noyywrap
+%option nounput
+%option reentrant
+%option extra-type="struct sqlcodeYY_state *"
%{
@@ -31,133 +35,261 @@
#include "config.h"
#include "filedef.h"
#include "tooltip.h"
+#include "message.h"
#define YY_NEVER_INTERACTIVE 1
#define YY_NO_INPUT 1
#define YY_NO_UNISTD_H 1
-static CodeOutputInterface * g_code;
-static QCString g_curClassName;
-static QCString g_parmType;
-static QCString g_parmName;
-static const char * g_inputString; //!< the code fragment as text
-static int g_inputPosition; //!< read offset during parsing
-static int g_inputLines; //!< number of line in the code fragment
-static int g_yyLineNr; //!< current line number
-static bool g_needsTermination;
-static Definition *g_searchCtx;
-
-static bool g_exampleBlock;
-static QCString g_exampleName;
-static QCString g_exampleFile;
-
-static QCString g_type;
-static QCString g_name;
-static QCString g_args;
-static QCString g_classScope;
-
-static QCString g_CurrScope;
-
-static FileDef * g_sourceFileDef;
-static Definition * g_currentDefinition;
-static MemberDef * g_currentMemberDef;
-static bool g_includeCodeFragment;
-static const char * g_currentFontClass;
-
-static void codify(const char* text)
+struct sqlcodeYY_state
+{
+ CodeOutputInterface * code;
+ const char *inputString; //!< the code fragment as text
+ int inputPosition; //!< read offset during parsing
+ int inputLines; //!< number of line in the code fragment
+ int yyLineNr; //!< current line number
+ bool needsTermination;
+ const Definition *searchCtx;
+
+ bool exampleBlock;
+ QCString exampleName;
+ QCString classScope;
+
+ FileDef *sourceFileDef;
+ Definition *currentDefinition;
+ MemberDef *currentMemberDef;
+ bool includeCodeFragment;
+ const char *currentFontClass;
+};
+
+static void codify(const char* text);
+static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner);
+static void startCodeLine(yyscan_t yyscanner);
+static void endFontClass(yyscan_t yyscanner);
+static void endCodeLine(yyscan_t yyscanner);
+static void nextCodeLine(yyscan_t yyscanner);
+static void codifyLines(char *text,yyscan_t yyscanner);
+static void startFontClass(const char *s,yyscan_t yyscanner);
+static int countLines(yyscan_t yyscanner);
+static int yyread(char *buf,int max_size,yyscan_t yyscanner);
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner);
+
+%}
+
+nl (\r\n|\r|\n)
+ws [ \t]+
+idchar [A-Za-z0-9\-_]+
+keywords1 ("ADD"|"ALL"|"ALLOCATE"|"ALTER"|"AND"|"ANY"|"ARE"|"AS"|"ASENSITIVE"|"ASYMMETRIC"|"AT"|"ATOMIC"|"AUTHORIZATION"|"BETWEEN"|"BOTH"|"BY"|"CALL"|"CALLED"|"CASCADED"|"CAST")
+keywords2 ("CHECK"|"CLOSE"|"COLLATE"|"COLUMN"|"COMMIT"|"CONNECT"|"CONSTRAINT"|"CONTINUE"|"CORRESPONDING"|"CREATE"|"CROSS"|"CUBE"|"CURRENT"|"CURRENT_DATE"|"CURRENT_DEFAULT_TRANSFORM_GROUP")
+keywords3 ("CURRENT_PATH"|"CURRENT_ROLE"|"CURRENT_TIME"|"CURRENT_TIMESTAMP"|"CURRENT_TRANSFORM_GROUP_FOR_TYPE"|"CURRENT_USER")
+keywords4 ("CURSOR"|"CYCLE"|"DAY"|"DEALLOCATE"|"DECLARE"|"DEFAULT"|"DELETE"|"DEREF"|"DESCRIBE"|"DETERMINISTIC"|"DISCONNECT"|"DISTINCT"|"DROP"|"DYNAMIC")
+keywords5 ("EACH"|"ELEMENT"|"END-EXEC"|"ESCAPE"|"EXCEPT"|"EXEC"|"EXECUTE"|"EXISTS"|"EXTERNAL"|"FETCH"|"FILTER"|"FOR"|"FOREIGN"|"FREE"|"FROM"|"FULL"|"FUNCTION")
+keywords6 ("GET"|"GLOBAL"|"GRANT"|"GROUP"|"GROUPING"|"HAVING"|"HOLD"|"HOUR"|"IDENTITY"|"IMMEDIATE"|"IN"|"INDICATOR"|"INNER"|"INOUT"|"INPUT"|"INSENSITIVE"|"INSERT"|"INTERSECT")
+keywords7 ("INTERVAL"|"INTO"|"IS"|"ISOLATION"|"JOIN"|"LANGUAGE"|"LARGE"|"LATERAL"|"LEADING"|"LEFT"|"LIKE"|"LOCAL"|"LOCALTIME"|"LOCALTIMESTAMP"|"MATCH"|"MEMBER"|"MERGE"|"METHOD"|"MINUTE")
+keywords8 ("MODIFIES"|"MODULE"|"MONTH"|"MULTISET"|"NATIONAL"|"NATURAL"|"NEW"|"NO"|"NONE"|"NOT"|"OF"|"OLD"|"ON"|"ONLY"|"OPEN"|"OR"|"ORDER"|"OUT"|"OUTER"|"OUTPUT")
+keywords9 ("OVER"|"OVERLAPS"|"PARAMETER"|"PARTITION"|"PRECISION"|"PREPARE"|"PRIMARY"|"PROCEDURE"|"RANGE"|"READS"|"RECURSIVE"|"REF"|"REFERENCES"|"REFERENCING"|"REGR_AVGX"|"REGR_AVGY")
+keywords10 ("REGR_COUNT"|"REGR_INTERCEPT"|"REGR_R2"|"REGR_SLOPE"|"REGR_SXX"|"REGR_SXY"|"REGR_SYY"|"RELEASE"|"RESULT"|"RETURN"|"RETURNS"|"REVOKE"|"RIGHT"|"ROLLBACK"|"ROLLUP"|"ROW"|"ROWS"|"SAVEPOINT")
+keywords11 ("SCROLL"|"SEARCH"|"SECOND"|"SELECT"|"SENSITIVE"|"SESSION_USER"|"SET"|"SIMILAR"|"SOME"|"SPECIFIC"|"SPECIFICTYPE"|"SQL"|"SQLEXCEPTION"|"SQLSTATE"|"SQLWARNING"|"START"|"STATIC")
+keywords12 ("SUBMULTISET"|"SYMMETRIC"|"SYSTEM"|"SYSTEM_USER"|"TABLE"|"THEN"|"TIMEZONE_HOUR"|"TIMEZONE_MINUTE"|"TO"|"TRAILING"|"TRANSLATION"|"TREAT"|"TRIGGER"|"UESCAPE"|"UNION")
+keywords13 ("UNIQUE"|"UNNEST"|"UPDATE"|"UPPER"|"USER"|"USING"|"VALUE"|"VALUES"|"VAR_POP"|"VAR_SAMP"|"VARYING"|"WHEN"|"WHENEVER"|"WHERE"|"WIDTH_BUCKET"|"WINDOW"|"WITH"|"WITHIN"|"WITHOUT"|"YEAR")
+
+/* Need multiple keyword definitions due to max length */
+keyword (?i:{keywords1}|{keywords2}|{keywords3}|{keywords4}|{keywords5}|{keywords6}|{keywords7}|{keywords8}|{keywords9}|{keywords10}|{keywords11}|{keywords12}|{keywords13})
+
+typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER"|"CLOB"|"DATE"|"DEC"|"DECIMAL"|"DOUBLE"|"FLOAT"|"INT"|"INTEGER"|"NCHAR"|"NCLOB"|"NUMERIC"|"NVARCHAR"|"REAL"|"SMALLINT"|"TIME"|"TIMESTAMP"|"VARCHAR")
+
+flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE")
+
+literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN")
+stringliteral (\"[^"]*\")|('[^']*')
+number [0-9]+
+literals ({literalkeyword}|{stringliteral}|{number})
+
+variable @{idchar}+
+
+simplecomment --.*
+commentopen "/\*"
+commentclose "\*/"
+
+%x COMMENT
+
+%%
+
+{literals} {
+ startFontClass("stringliteral",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+
+{keyword} {
+ startFontClass("keyword",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+{flowkeyword} {
+ startFontClass("keywordflow",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+{typekeyword} {
+ startFontClass("keywordtype",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+{variable} {
+ startFontClass("preprocessor",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+{simplecomment} {
+ startFontClass("comment",yyscanner);
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ }
+
+{commentopen} {
+ startFontClass("comment",yyscanner);
+ codifyLines(yytext,yyscanner);
+ BEGIN(COMMENT);
+ }
+
+<COMMENT>. {
+ codifyLines(yytext,yyscanner);
+
+ }
+<COMMENT>{nl} {
+ codifyLines(yytext,yyscanner);
+ }
+
+<COMMENT>{commentclose} {
+ codifyLines(yytext,yyscanner);
+ endFontClass(yyscanner);
+ BEGIN(INITIAL);
+ }
+
+{idchar} {
+ codifyLines(yytext,yyscanner);
+ }
+
+{nl} {
+ codifyLines(yytext,yyscanner);
+ }
+
+. {
+ codifyLines(yytext,yyscanner);
+ }
+
+%%
+
+
+static void codify(const char* text, yyscan_t yyscanner)
{
- g_code->codify(text);
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ yyextra->code->codify(text);
}
-static void setCurrentDoc(const QCString &anchor)
+static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
if (Doxygen::searchIndex)
{
- if (g_searchCtx)
+ if (yyextra->searchCtx)
{
- Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
+ Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE);
}
else
{
- Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
+ Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE);
}
}
}
-/*! start a new line of code, inserting a line number if g_sourceFileDef
+/*! start a new line of code, inserting a line number if yyextra->sourceFileDef
* is TRUE. If a definition starts at the current line, then the line
* number is linked to the documentation of that definition.
*/
-static void startCodeLine()
+static void startCodeLine(yyscan_t yyscanner)
{
- if (g_sourceFileDef)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ if (yyextra->sourceFileDef)
{
- Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
+ Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
- if (!g_includeCodeFragment && d && d->isLinkableInProject())
+ if (!yyextra->includeCodeFragment && d && d->isLinkableInProject())
{
- g_currentDefinition = d;
- g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
- g_classScope = d->name().copy();
+ yyextra->currentDefinition = d;
+ yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
+ yyextra->classScope = d->name().copy();
QCString lineAnchor;
- lineAnchor.sprintf("l%05d",g_yyLineNr);
- if (g_currentMemberDef)
+ lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
+ if (yyextra->currentMemberDef)
{
- g_code->writeLineNumber(g_currentMemberDef->getReference(),
- g_currentMemberDef->getOutputFileBase(),
- g_currentMemberDef->anchor(),g_yyLineNr);
- setCurrentDoc(lineAnchor);
+ yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
+ yyextra->currentMemberDef->getOutputFileBase(),
+ yyextra->currentMemberDef->anchor(),yyextra->yyLineNr);
+ setCurrentDoc(lineAnchor,yyscanner);
}
else
{
- g_code->writeLineNumber(d->getReference(),
+ yyextra->code->writeLineNumber(d->getReference(),
d->getOutputFileBase(),
- 0,g_yyLineNr);
- setCurrentDoc(lineAnchor);
+ 0,yyextra->yyLineNr);
+ setCurrentDoc(lineAnchor,yyscanner);
}
}
else
{
- g_code->writeLineNumber(0,0,0,g_yyLineNr);
+ yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr);
}
}
- g_code->startCodeLine(g_sourceFileDef);
+ yyextra->code->startCodeLine(yyextra->sourceFileDef);
- if (g_currentFontClass)
+ if (yyextra->currentFontClass)
{
- g_code->startFontClass(g_currentFontClass);
+ yyextra->code->startFontClass(yyextra->currentFontClass);
}
}
-static void endFontClass()
+static void endFontClass(yyscan_t yyscanner)
{
- if (g_currentFontClass)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ if (yyextra->currentFontClass)
{
- g_code->endFontClass();
- g_currentFontClass=0;
+ yyextra->code->endFontClass();
+ yyextra->currentFontClass=0;
}
}
-static void endCodeLine()
+static void endCodeLine(yyscan_t yyscanner)
{
- endFontClass();
- g_code->endCodeLine();
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ endFontClass(yyscanner);
+ yyextra->code->endCodeLine();
}
-static void nextCodeLine()
+static void nextCodeLine(yyscan_t yyscanner)
{
- const char *fc = g_currentFontClass;
- endCodeLine();
- if (g_yyLineNr<g_inputLines)
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ const char *fc = yyextra->currentFontClass;
+ endCodeLine(yyscanner);
+ if (yyextra->yyLineNr<yyextra->inputLines)
{
- g_currentFontClass = fc;
- startCodeLine();
+ yyextra->currentFontClass = fc;
+ startCodeLine(yyscanner);
}
}
-static void codifyLines(char *text)
+static void codifyLines(char *text,yyscan_t yyscanner)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
char *p=text,*sp=p;
char c;
bool done=FALSE;
@@ -170,30 +302,32 @@ static void codifyLines(char *text)
if (c=='\n')
{
- g_yyLineNr++;
+ yyextra->yyLineNr++;
*(p-1)='\0';
- g_code->codify(sp);
- nextCodeLine();
+ yyextra->code->codify(sp);
+ nextCodeLine(yyscanner);
}
else
{
- g_code->codify(sp);
+ yyextra->code->codify(sp);
done=TRUE;
}
}
}
-static void startFontClass(const char *s)
+static void startFontClass(const char *s,yyscan_t yyscanner)
{
- endFontClass();
- g_code->startFontClass(s);
- g_currentFontClass=s;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ endFontClass(yyscanner);
+ yyextra->code->startFontClass(s);
+ yyextra->currentFontClass=s;
}
/*! counts the number of lines in the input */
-static int countLines()
+static int countLines(yyscan_t yyscanner)
{
- const char *p=g_inputString;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ const char *p=yyextra->inputString;
char c;
int count=1;
while ((c=*p))
@@ -201,142 +335,31 @@ static int countLines()
p++ ;
if (c=='\n') count++;
}
- if (p>g_inputString && *(p-1)!='\n')
+ if (p>yyextra->inputString && *(p-1)!='\n')
{ // last line does not end with a \n, so we add an extra
// line and explicitly terminate the line after parsing.
count++,
- g_needsTermination=TRUE;
+ yyextra->needsTermination=TRUE;
}
return count;
}
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
-
-static int yyread(char *buf,int max_size)
+static int yyread(char *buf,int max_size,yyscan_t yyscanner)
{
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
int c=0;
- while( c < max_size && g_inputString[g_inputPosition] )
+ while( c < max_size && yyextra->inputString[yyextra->inputPosition] )
{
- *buf = g_inputString[g_inputPosition++] ;
+ *buf = yyextra->inputString[yyextra->inputPosition++] ;
c++; buf++;
}
return c;
}
-%}
-
-nl (\r\n|\r|\n)
-ws [ \t]+
-idchar [A-Za-z0-9\-_]+
-keywords1 ("ADD"|"ALL"|"ALLOCATE"|"ALTER"|"AND"|"ANY"|"ARE"|"AS"|"ASENSITIVE"|"ASYMMETRIC"|"AT"|"ATOMIC"|"AUTHORIZATION"|"BETWEEN"|"BOTH"|"BY"|"CALL"|"CALLED"|"CASCADED"|"CAST")
-keywords2 ("CHECK"|"CLOSE"|"COLLATE"|"COLUMN"|"COMMIT"|"CONNECT"|"CONSTRAINT"|"CONTINUE"|"CORRESPONDING"|"CREATE"|"CROSS"|"CUBE"|"CURRENT"|"CURRENT_DATE"|"CURRENT_DEFAULT_TRANSFORM_GROUP")
-keywords3 ("CURRENT_PATH"|"CURRENT_ROLE"|"CURRENT_TIME"|"CURRENT_TIMESTAMP"|"CURRENT_TRANSFORM_GROUP_FOR_TYPE"|"CURRENT_USER")
-keywords4 ("CURSOR"|"CYCLE"|"DAY"|"DEALLOCATE"|"DECLARE"|"DEFAULT"|"DELETE"|"DEREF"|"DESCRIBE"|"DETERMINISTIC"|"DISCONNECT"|"DISTINCT"|"DROP"|"DYNAMIC")
-keywords5 ("EACH"|"ELEMENT"|"END-EXEC"|"ESCAPE"|"EXCEPT"|"EXEC"|"EXECUTE"|"EXISTS"|"EXTERNAL"|"FETCH"|"FILTER"|"FOR"|"FOREIGN"|"FREE"|"FROM"|"FULL"|"FUNCTION")
-keywords6 ("GET"|"GLOBAL"|"GRANT"|"GROUP"|"GROUPING"|"HAVING"|"HOLD"|"HOUR"|"IDENTITY"|"IMMEDIATE"|"IN"|"INDICATOR"|"INNER"|"INOUT"|"INPUT"|"INSENSITIVE"|"INSERT"|"INTERSECT")
-keywords7 ("INTERVAL"|"INTO"|"IS"|"ISOLATION"|"JOIN"|"LANGUAGE"|"LARGE"|"LATERAL"|"LEADING"|"LEFT"|"LIKE"|"LOCAL"|"LOCALTIME"|"LOCALTIMESTAMP"|"MATCH"|"MEMBER"|"MERGE"|"METHOD"|"MINUTE")
-keywords8 ("MODIFIES"|"MODULE"|"MONTH"|"MULTISET"|"NATIONAL"|"NATURAL"|"NEW"|"NO"|"NONE"|"NOT"|"OF"|"OLD"|"ON"|"ONLY"|"OPEN"|"OR"|"ORDER"|"OUT"|"OUTER"|"OUTPUT")
-keywords9 ("OVER"|"OVERLAPS"|"PARAMETER"|"PARTITION"|"PRECISION"|"PREPARE"|"PRIMARY"|"PROCEDURE"|"RANGE"|"READS"|"RECURSIVE"|"REF"|"REFERENCES"|"REFERENCING"|"REGR_AVGX"|"REGR_AVGY")
-keywords10 ("REGR_COUNT"|"REGR_INTERCEPT"|"REGR_R2"|"REGR_SLOPE"|"REGR_SXX"|"REGR_SXY"|"REGR_SYY"|"RELEASE"|"RESULT"|"RETURN"|"RETURNS"|"REVOKE"|"RIGHT"|"ROLLBACK"|"ROLLUP"|"ROW"|"ROWS"|"SAVEPOINT")
-keywords11 ("SCROLL"|"SEARCH"|"SECOND"|"SELECT"|"SENSITIVE"|"SESSION_USER"|"SET"|"SIMILAR"|"SOME"|"SPECIFIC"|"SPECIFICTYPE"|"SQL"|"SQLEXCEPTION"|"SQLSTATE"|"SQLWARNING"|"START"|"STATIC")
-keywords12 ("SUBMULTISET"|"SYMMETRIC"|"SYSTEM"|"SYSTEM_USER"|"TABLE"|"THEN"|"TIMEZONE_HOUR"|"TIMEZONE_MINUTE"|"TO"|"TRAILING"|"TRANSLATION"|"TREAT"|"TRIGGER"|"UESCAPE"|"UNION")
-keywords13 ("UNIQUE"|"UNNEST"|"UPDATE"|"UPPER"|"USER"|"USING"|"VALUE"|"VALUES"|"VAR_POP"|"VAR_SAMP"|"VARYING"|"WHEN"|"WHENEVER"|"WHERE"|"WIDTH_BUCKET"|"WINDOW"|"WITH"|"WITHIN"|"WITHOUT"|"YEAR")
-
-/* Need multiple keyword definitions due to max length */
-keyword (?i:{keywords1}|{keywords2}|{keywords3}|{keywords4}|{keywords5}|{keywords6}|{keywords7}|{keywords8}|{keywords9}|{keywords10}|{keywords11}|{keywords12}|{keywords13})
-
-typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER"|"CLOB"|"DATE"|"DEC"|"DECIMAL"|"DOUBLE"|"FLOAT"|"INT"|"INTEGER"|"NCHAR"|"NCLOB"|"NUMERIC"|"NVARCHAR"|"REAL"|"SMALLINT"|"TIME"|"TIMESTAMP"|"VARCHAR")
-
-flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE")
-
-literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN")
-stringliteral (\"[^"]*\")|('[^']*')
-number [0-9]+
-literals ({literalkeyword}|{stringliteral}|{number})
-variable @{idchar}+
-
-simplecomment --.*
-commentopen "/\*"
-commentclose "\*/"
-
-%option noyywrap
-%option nounput
-
-%x COMMENT
-
-%%
-
-{literals} {
- startFontClass("stringliteral");
- codifyLines(yytext);
- endFontClass();
- }
-
-
-{keyword} {
- startFontClass("keyword");
- codifyLines(yytext);
- endFontClass();
- }
-
-{flowkeyword} {
- startFontClass("keywordflow");
- codifyLines(yytext);
- endFontClass();
- }
-
-{typekeyword} {
- startFontClass("keywordtype");
- codifyLines(yytext);
- endFontClass();
- }
-
-{variable} {
- startFontClass("preprocessor");
- codifyLines(yytext);
- endFontClass();
- }
-
-{simplecomment} {
- startFontClass("comment");
- codifyLines(yytext);
- endFontClass();
- }
-
-{commentopen} {
- startFontClass("comment");
- codifyLines(yytext);
- BEGIN(COMMENT);
- }
-
-<COMMENT>. {
- codifyLines(yytext);
- }
-<COMMENT>{nl} {
- codifyLines(yytext);
- }
-
-<COMMENT>{commentclose} {
- codifyLines(yytext);
- endFontClass();
- BEGIN(INITIAL);
- }
-
-{idchar} {
- codifyLines(yytext);
- }
-
-{nl} {
- codifyLines(yytext);
- }
-
-. {
- codifyLines(yytext);
- }
-
-%%
+// public interface -----------------------------------------------------------
+static yyscan_t yyscanner;
+static struct sqlcodeYY_state sqlcode_extra;
void parseSqlCode(
CodeOutputInterface &od,
@@ -348,74 +371,86 @@ void parseSqlCode(
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *,
- bool,Definition *searchCtx,
+ const MemberDef *,
+ bool,const Definition *searchCtx,
bool /*collectXRefs*/
)
{
if (s.isEmpty()) return;
+
+ sqlcodeYYlex_init_extra(&sqlcode_extra, &yyscanner);
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+
+#ifdef FLEX_DEBUG
+ yyset_debug(1,yyscanner);
+#endif
+
+ printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
- g_code = &od;
- g_inputString = s;
- g_inputPosition = 0;
- g_currentFontClass = 0;
- g_needsTermination = FALSE;
- g_searchCtx=searchCtx;
+ yyextra->code = &od;
+ yyextra->inputString = s;
+ yyextra->inputPosition = 0;
+ yyextra->currentFontClass = 0;
+ yyextra->needsTermination = FALSE;
+ yyextra->searchCtx=searchCtx;
if (startLine!=-1)
- g_yyLineNr = startLine;
+ yyextra->yyLineNr = startLine;
else
- g_yyLineNr = 1;
+ yyextra->yyLineNr = 1;
if (endLine!=-1)
- g_inputLines = endLine+1;
+ yyextra->inputLines = endLine+1;
else
- g_inputLines = g_yyLineNr + countLines() - 1;
+ yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
- g_exampleBlock = exBlock;
- g_exampleName = exName;
- g_sourceFileDef = fd;
+ yyextra->exampleBlock = exBlock;
+ yyextra->exampleName = exName;
+ yyextra->sourceFileDef = fd;
bool cleanupSourceDef = FALSE;
if (exBlock && fd==0)
{
// create a dummy filedef for the example
- g_sourceFileDef = createFileDef("",(exName?exName:"generated"));
+ yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated"));
cleanupSourceDef = TRUE;
}
- if (g_sourceFileDef)
+ if (yyextra->sourceFileDef)
{
- setCurrentDoc("l00001");
+ setCurrentDoc("l00001",yyscanner);
}
- g_includeCodeFragment = inlineFragment;
+ yyextra->includeCodeFragment = inlineFragment;
// Starts line 1 on the output
- startCodeLine();
+ startCodeLine(yyscanner);
- sqlcodeYYrestart( sqlcodeYYin );
+ sqlcodeYYrestart( yyin,yyscanner );
- sqlcodeYYlex();
+ sqlcodeYYlex(yyscanner);
- if (g_needsTermination)
+ if (yyextra->needsTermination)
{
- endCodeLine();
+ endCodeLine(yyscanner);
}
if (cleanupSourceDef)
{
// delete the temporary file definition used for this example
- delete g_sourceFileDef;
- g_sourceFileDef=0;
+ delete yyextra->sourceFileDef;
+ yyextra->sourceFileDef=0;
}
+ printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
+ sqlcodeYYlex_destroy(yyscanner);
return;
}
void resetSqlCodeParserState()
{
- g_currentDefinition = 0;
- g_currentMemberDef = 0;
+ struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
+ yyextra->currentDefinition = 0;
+ yyextra->currentMemberDef = 0;
}
#if !defined(YY_FLEX_SUBMINOR_VERSION)
diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp
index a1ea115..012a0c0 100644
--- a/src/sqlite3gen.cpp
+++ b/src/sqlite3gen.cpp
@@ -1015,16 +1015,16 @@ static void insertMemberReference(const MemberDef *src, const MemberDef *dst, co
static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def)
{
- ArgumentList *declAl = md->declArgumentList();
- ArgumentList *defAl = md->argumentList();
+ const ArgumentList *declAl = md->declArgumentList();
+ const ArgumentList *defAl = md->argumentList();
if (declAl!=0 && defAl!=0 && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
- Argument *a;
+ const Argument *a;
for (declAli.toFirst();(a=declAli.current());++declAli)
{
- Argument *defArg = defAli.current();
+ const Argument *defArg = defAli.current();
if (!a->attrib.isEmpty())
{
@@ -1410,7 +1410,7 @@ static void writeTemplateArgumentList(const ArgumentList * al,
static void writeMemberTemplateLists(const MemberDef *md)
{
- ArgumentList *templMd = md->templateArguments();
+ const ArgumentList *templMd = md->templateArguments();
if (templMd) // function template prefix
{
writeTemplateArgumentList(templMd,md->getClassDef(),md->getFileDef());
@@ -1434,7 +1434,7 @@ QCString getSQLDocBlock(const Definition *scope,
fileName,
lineNr,
const_cast<Definition*>(scope),
- const_cast<MemberDef*>(reinterpret_cast<const MemberDef*>(def)),
+ dynamic_cast<const MemberDef*>(def),
doc,
FALSE,
FALSE
@@ -1675,7 +1675,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref
if (isFunc)
{
- ArgumentList *al = md->argumentList();
+ const ArgumentList *al = md->argumentList();
if (al!=0)
{
bindIntParameter(memberdef_insert,":const",al->constSpecifier);
@@ -2009,7 +2009,11 @@ static void generateSqlite3ForClass(const ClassDef *cd)
if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
if (!nm.isEmpty())
{
- int header_id=insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference());
+ int header_id=-1;
+ if (ii->fileDef)
+ {
+ insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference());
+ }
DBG_CTX(("-----> ClassDef includeInfo for %s\n", nm.data()));
DBG_CTX((" local : %d\n", ii->local));
DBG_CTX((" imported : %d\n", ii->imported));
diff --git a/src/sqlscanner.h b/src/sqlscanner.h
index 7afa869..3ca6fe3 100644
--- a/src/sqlscanner.h
+++ b/src/sqlscanner.h
@@ -41,9 +41,9 @@ public:
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
)
{
diff --git a/src/tclscanner.h b/src/tclscanner.h
index aa1673c..0e56bdd 100644
--- a/src/tclscanner.h
+++ b/src/tclscanner.h
@@ -47,9 +47,9 @@ class TclLanguageScanner : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
void resetCodeParserState();
diff --git a/src/tclscanner.l b/src/tclscanner.l
index 88714ce..9ec512a 100644
--- a/src/tclscanner.l
+++ b/src/tclscanner.l
@@ -456,7 +456,7 @@ static struct
QAsciiDict<Entry> fn; // all read function entries
QList<Entry> entry; // list of all created entries, will be deleted after codifying
Protection protection; // current protections state
- MemberDef *memberdef; // contain current MemberDef when codifying
+ const MemberDef *memberdef; // contain current MemberDef when codifying
bool collectXRefs;
} tcl;
@@ -486,7 +486,7 @@ Entry* tcl_entry_new()
// myEntry->stat = FALSE;
myEntry->fileName = tcl.file_name;
myEntry->lang = SrcLangExt_Tcl;
- initGroupInfo(myEntry);
+ Doxygen::docGroup.initGroupInfo(myEntry);
// collect entries
if (!tcl.code)
{
@@ -1722,7 +1722,7 @@ static void tcl_codify_link(QCString name)
if (tcl.memberdef)
{
myDef->addSourceReferencedBy(tcl.memberdef);
- tcl.memberdef->addSourceReferences(myDef);
+ //tcl.memberdef->addSourceReferences(myDef);
} else {
Entry* callerEntry;
unsigned int i;
@@ -2950,7 +2950,7 @@ tcl_inf("%s\n",fileName);
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
msg("Parsing %s...\n",fileName);
- groupEnterFile(fileName,yylineno);
+ Doxygen::docGroup.enterFile(fileName,yylineno);
tcl_init();
tcl.code = NULL;
@@ -2958,7 +2958,7 @@ tcl_inf("%s\n",fileName);
tcl.this_parser = this;
tcl.entry_main = root; /* toplevel entry */
tcl_parse("","");
- groupLeaveFile(tcl.file_name,yylineno);
+ Doxygen::docGroup.leaveFile(tcl.file_name,yylineno);
root->program.resize(0);
myFile.close();
printlex(yy_flex_debug, FALSE, __FILE__, fileName);
@@ -2975,9 +2975,9 @@ void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
diff --git a/src/textdocvisitor.h b/src/textdocvisitor.h
index bbc70e8..c4ba3d7 100644
--- a/src/textdocvisitor.h
+++ b/src/textdocvisitor.h
@@ -125,8 +125,6 @@ class TextDocVisitor : public DocVisitor
void visitPost(DocXRefItem *) {}
void visitPre(DocInternalRef *) {}
void visitPost(DocInternalRef *) {}
- void visitPre(DocCopy *) {}
- void visitPost(DocCopy *) {}
void visitPre(DocText *) {}
void visitPost(DocText *) {}
void visitPre(DocHtmlBlockQuote *) {}
diff --git a/src/tooltip.cpp b/src/tooltip.cpp
index 2c6f6e1..a30a85c 100644
--- a/src/tooltip.cpp
+++ b/src/tooltip.cpp
@@ -68,7 +68,7 @@ static QCString escapeId(const char *s)
return res;
}
-void TooltipManager::addTooltip(Definition *d)
+void TooltipManager::addTooltip(const Definition *d)
{
static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
if (!sourceTooltips) return;
diff --git a/src/tooltip.h b/src/tooltip.h
index 34a578a..170ea3c 100644
--- a/src/tooltip.h
+++ b/src/tooltip.h
@@ -23,7 +23,7 @@ class TooltipManager
public:
static TooltipManager *instance();
void clearTooltips();
- void addTooltip(Definition *d);
+ void addTooltip(const Definition *d);
void writeTooltips(CodeOutputInterface &ol);
private:
diff --git a/src/util.cpp b/src/util.cpp
index 507ced9..695a52c 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -346,8 +346,8 @@ int guessSection(const char *name)
return 0;
}
-QCString resolveTypeDef(Definition *context,const QCString &qualifiedName,
- Definition **typedefContext)
+QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName,
+ const Definition **typedefContext)
{
//printf("<<resolveTypeDef(%s,%s)\n",
// context ? context->name().data() : "<none>",qualifiedName.data());
@@ -358,7 +358,7 @@ QCString resolveTypeDef(Definition *context,const QCString &qualifiedName,
return result;
}
- Definition *mContext=context;
+ const Definition *mContext=context;
if (typedefContext) *typedefContext=context;
// see if the qualified name has a scope part
@@ -378,7 +378,7 @@ QCString resolveTypeDef(Definition *context,const QCString &qualifiedName,
while (mContext && md==0)
{
// step 1: get the right scope
- Definition *resScope=mContext;
+ const Definition *resScope=mContext;
if (scopeIndex!=-1)
{
// split-off scope part
@@ -518,10 +518,10 @@ static QDict<MemberDef> g_resolvedTypedefs;
static QDict<Definition> g_visitedNamespaces;
// forward declaration
-static ClassDef *getResolvedClassRec(const Definition *scope,
+static const ClassDef *getResolvedClassRec(const Definition *scope,
const FileDef *fileScope,
const char *n,
- MemberDef **pTypeDef,
+ const MemberDef **pTypeDef,
QCString *pTemplSpec,
QCString *pResolvedType
);
@@ -535,10 +535,12 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop
*
* Example: typedef int T; will return 0, since "int" is not a class.
*/
-ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md,
- MemberDef **pMemType,QCString *pTemplSpec,
- QCString *pResolvedType,
- ArgumentList *actTemplParams)
+const ClassDef *newResolveTypedef(const FileDef *fileScope,
+ const MemberDef *md,
+ const MemberDef **pMemType,
+ QCString *pTemplSpec,
+ QCString *pResolvedType,
+ ArgumentList *actTemplParams)
{
//printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal());
bool isCached = md->isTypedefValCached(); // value already cached
@@ -559,7 +561,7 @@ ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md,
g_resolvedTypedefs.insert(qname,md); // put on the trace list
- ClassDef *typeClass = md->getClassDef();
+ const ClassDef *typeClass = md->getClassDef();
QCString type = md->typeString(); // get the "value" of the typedef
if (typeClass && typeClass->isTemplate() &&
actTemplParams && actTemplParams->count()>0)
@@ -581,8 +583,8 @@ ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md,
int sp=0;
tl=type.length(); // length may have been changed
while (sp<tl && type.at(sp)==' ') sp++;
- MemberDef *memTypeDef = 0;
- ClassDef *result = getResolvedClassRec(md->getOuterScope(),
+ const MemberDef *memTypeDef = 0;
+ const ClassDef *result = getResolvedClassRec(md->getOuterScope(),
fileScope,type,&memTypeDef,0,pResolvedType);
// if type is a typedef then return what it resolves to.
if (memTypeDef && memTypeDef->isTypedef())
@@ -652,7 +654,7 @@ done:
//printf("setting cached typedef %p in result %p\n",md,result);
//printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine());
//printf("*pResolvedType=%s\n",pResolvedType?pResolvedType->data():"<none>");
- md->cacheTypedefVal(result,
+ const_cast<MemberDef*>(md)->cacheTypedefVal(result,
pTemplSpec ? *pTemplSpec : QCString(),
pResolvedType ? *pResolvedType : QCString()
);
@@ -667,7 +669,7 @@ done:
* value of the typedef or \a name if no typedef was found.
*/
static QCString substTypedef(const Definition *scope,const FileDef *fileScope,const QCString &name,
- MemberDef **pTypeDef=0)
+ const MemberDef **pTypeDef=0)
{
QCString result=name;
if (name.isEmpty()) return result;
@@ -730,7 +732,7 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co
return result;
}
-static Definition *endOfPathIsUsedClass(SDict<Definition> *cl,const QCString &localName)
+static const Definition *endOfPathIsUsedClass(const SDict<Definition> *cl,const QCString &localName)
{
if (cl)
{
@@ -763,12 +765,12 @@ static const Definition *followPath(const Definition *start,const FileDef *fileS
while ((is=getScopeFragment(path,ps,&l))!=-1)
{
// try to resolve the part if it is a typedef
- MemberDef *typeDef=0;
+ const MemberDef *typeDef=0;
QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef);
//printf(" qualScopePart=%s\n",qualScopePart.data());
if (typeDef)
{
- ClassDef *type = newResolveTypedef(fileScope,typeDef);
+ const ClassDef *type = newResolveTypedef(fileScope,typeDef);
if (type)
{
//printf("Found type %s\n",type->name().data());
@@ -852,18 +854,21 @@ bool accessibleViaUsingNamespace(const NamespaceSDict *nl,
//printf("] found it\n");
return TRUE;
}
- QCString key=und->name();
- if (und->getUsedNamespaces() && visitedDict.find(key)==0)
+ if (item->getLanguage()==SrcLangExt_Cpp)
{
- visitedDict.insert(key,(void *)0x08);
-
- if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart))
+ QCString key=und->name();
+ if (und->getUsedNamespaces() && visitedDict.find(key)==0)
{
- //printf("] found it via recursion\n");
- return TRUE;
- }
+ visitedDict.insert(key,(void *)0x08);
+
+ if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart))
+ {
+ //printf("] found it via recursion\n");
+ return TRUE;
+ }
- visitedDict.remove(key);
+ visitedDict.remove(key);
+ }
}
//printf("] Try via used namespace done\n");
}
@@ -1011,13 +1016,13 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi
{
const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope);
//printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses());
- SDict<Definition> *cl = nscope->getUsedClasses();
+ const SDict<Definition> *cl = nscope->getUsedClasses();
if (accessibleViaUsingClass(cl,fileScope,item))
{
//printf("> found via used class\n");
goto done;
}
- NamespaceSDict *nl = nscope->getUsedNamespaces();
+ const NamespaceSDict *nl = nscope->getUsedNamespaces();
if (accessibleViaUsingNamespace(nl,fileScope,item))
{
//printf("> found via used namespace\n");
@@ -1115,11 +1120,11 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop
// in A via a using directive.
//printf("newScope is a namespace: %s!\n",newScope->name().data());
const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(newScope);
- SDict<Definition> *cl = nscope->getUsedClasses();
+ const SDict<Definition> *cl = nscope->getUsedClasses();
if (cl)
{
SDict<Definition>::Iterator cli(*cl);
- Definition *cd;
+ const Definition *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
//printf("Trying for class %s\n",cd->name().data());
@@ -1130,11 +1135,11 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop
}
}
}
- NamespaceSDict *nl = nscope->getUsedNamespaces();
+ const NamespaceSDict *nl = nscope->getUsedNamespaces();
if (nl)
{
NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
if (g_visitedNamespaces.find(nd->name())==0)
@@ -1166,7 +1171,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop
if (scope->definitionType()==Definition::TypeNamespace)
{
const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope);
- NamespaceSDict *nl = nscope->getUsedNamespaces();
+ const NamespaceSDict *nl = nscope->getUsedNamespaces();
if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart))
{
//printf("> found in used namespace\n");
@@ -1177,7 +1182,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop
{
if (fileScope)
{
- NamespaceSDict *nl = fileScope->getUsedNamespaces();
+ const NamespaceSDict *nl = fileScope->getUsedNamespaces();
if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart))
{
//printf("> found in used namespace\n");
@@ -1215,8 +1220,8 @@ static void getResolvedSymbol(const Definition *scope,
const QCString &explicitScopePart,
ArgumentList *actTemplParams,
int &minDistance,
- ClassDef *&bestMatch,
- MemberDef *&bestTypedef,
+ const ClassDef *&bestMatch,
+ const MemberDef *&bestTypedef,
QCString &bestTemplSpec,
QCString &bestResolvedType
)
@@ -1303,8 +1308,8 @@ static void getResolvedSymbol(const Definition *scope,
QCString spec;
QCString type;
minDistance=distance;
- MemberDef *enumType = 0;
- ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams);
+ const MemberDef *enumType = 0;
+ const ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams);
if (cd) // type resolves to a class
{
//printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data());
@@ -1374,10 +1379,10 @@ static void getResolvedSymbol(const Definition *scope,
* match against the input name. Can recursively call itself when
* resolving typedefs.
*/
-static ClassDef *getResolvedClassRec(const Definition *scope,
+static const ClassDef *getResolvedClassRec(const Definition *scope,
const FileDef *fileScope,
const char *n,
- MemberDef **pTypeDef,
+ const MemberDef **pTypeDef,
QCString *pTemplSpec,
QCString *pResolvedType
)
@@ -1496,8 +1501,8 @@ static ClassDef *getResolvedClassRec(const Definition *scope,
Doxygen::lookupCache->insert(key,new LookupInfo);
}
- ClassDef *bestMatch=0;
- MemberDef *bestTypedef=0;
+ const ClassDef *bestMatch=0;
+ const MemberDef *bestTypedef=0;
QCString bestTemplSpec;
QCString bestResolvedType;
int minDistance=10000; // init at "infinite"
@@ -1563,10 +1568,10 @@ static ClassDef *getResolvedClassRec(const Definition *scope,
* Loops through scope and each of its parent scopes looking for a
* match against the input name.
*/
-ClassDef *getResolvedClass(const Definition *scope,
+const ClassDef *getResolvedClass(const Definition *scope,
const FileDef *fileScope,
const char *n,
- MemberDef **pTypeDef,
+ const MemberDef **pTypeDef,
QCString *pTemplSpec,
bool mayBeUnlinkable,
bool mayBeHidden,
@@ -1590,7 +1595,7 @@ ClassDef *getResolvedClass(const Definition *scope,
// n,
// mayBeUnlinkable
// );
- ClassDef *result;
+ const ClassDef *result;
if (optimizeOutputVhdl)
{
result = getClass(n);
@@ -1672,6 +1677,7 @@ struct CharAroundSpace
charMap['='].after=FALSE;
charMap[' '].after=FALSE;
+ charMap['['].after=FALSE;
charMap[']'].after=FALSE;
charMap['\t'].after=FALSE;
charMap['\n'].after=FALSE;
@@ -1869,7 +1875,7 @@ QCString removeRedundantWhiteSpace(const QCString &s)
case '@': // '@name' -> ' @name'
case '$': // '$name' -> ' $name'
case '\'': // ''name' -> '' name'
- if (i>0 && i<l-1 && pc!='=' && pc!=':' && !isspace(pc) &&
+ if (i>0 && i<l-1 && pc!='=' && pc!=':' && !isspace((uchar)pc) &&
isId(nc) && osp<8) // ")id" -> ") id"
{
*dst++=' ';
@@ -1913,14 +1919,14 @@ QCString removeRedundantWhiteSpace(const QCString &s)
default:
*dst++=c;
if (c=='t' && csp==5 && i<l-1 && // found 't' in 'const'
- !(isId(nc) || nc==')' || nc==',' || isspace(nc))
+ !(isId(nc) || nc==')' || nc==',' || isspace((uchar)nc))
) // prevent const ::A from being converted to const::A
{
*dst++=' ';
csp=0;
}
else if (c=='l' && vsp==7 && i<l-1 && // found 'l' in 'virtual'
- !(isId(nc) || nc==')' || nc==',' || isspace(nc))
+ !(isId(nc) || nc==')' || nc==',' || isspace((uchar)nc))
) // prevent virtual ::A from being converted to virtual::A
{
*dst++=' ';
@@ -2028,12 +2034,17 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
int floatingIndex=0;
if (strLen==0) return;
// read a word from the text string
- while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1 &&
- (newIndex==0 || !(txtStr.at(newIndex-1)>='0' && txtStr.at(newIndex-1)<='9')) // avoid matching part of hex numbers
- )
+ while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1)
{
- // add non-word part to the result
floatingIndex+=newIndex-skipIndex+matchLen;
+ if (newIndex>0 && txtStr.at(newIndex-1)=='0') // ignore hex numbers (match x00 in 0x00)
+ {
+ out.writeString(txtStr.mid(skipIndex,newIndex+matchLen-skipIndex),keepSpaces);
+ skipIndex=index=newIndex+matchLen;
+ continue;
+ }
+
+ // add non-word part to the result
bool insideString=FALSE;
int i;
for (i=index;i<newIndex;i++)
@@ -2077,14 +2088,14 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope,
bool found=FALSE;
if (!insideString)
{
- ClassDef *cd=0;
- FileDef *fd=0;
- MemberDef *md=0;
- NamespaceDef *nd=0;
- GroupDef *gd=0;
+ const MemberDef *md=0;
+ const ClassDef *cd=0;
+ const FileDef *fd=0;
+ const NamespaceDef *nd=0;
+ const GroupDef *gd=0;
//printf("** Match word '%s'\n",matchWord.data());
- MemberDef *typeDef=0;
+ const MemberDef *typeDef=0;
cd=getResolvedClass(scope,fileScope,matchWord,&typeDef);
if (typeDef) // First look at typedef then class, see bug 584184.
{
@@ -2249,12 +2260,12 @@ void writeExample(OutputList &ol,ExampleSDict *ed)
}
-QCString argListToString(ArgumentList *al,bool useCanonicalType,bool showDefVals)
+QCString argListToString(const ArgumentList *al,bool useCanonicalType,bool showDefVals)
{
QCString result;
if (al==0) return result;
ArgumentListIterator ali(*al);
- Argument *a=ali.current();
+ const Argument *a=ali.current();
result+="(";
while (a)
{
@@ -2297,13 +2308,13 @@ QCString argListToString(ArgumentList *al,bool useCanonicalType,bool showDefVals
return removeRedundantWhiteSpace(result);
}
-QCString tempArgListToString(ArgumentList *al,SrcLangExt lang)
+QCString tempArgListToString(const ArgumentList *al,SrcLangExt lang)
{
QCString result;
if (al==0) return result;
result="<";
ArgumentListIterator ali(*al);
- Argument *a=ali.current();
+ const Argument *a=ali.current();
while (a)
{
if (!a->name.isEmpty()) // add template argument name
@@ -2662,7 +2673,7 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level)
return m;
}
-Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection prot,int level)
+Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot,int level)
{
if (bcd->categoryOf()) // use class that is being extended in case of
// an Objective-C category
@@ -2681,7 +2692,7 @@ Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection p
else if (cd->baseClasses())
{
BaseClassListIterator bcli(*cd->baseClasses());
- BaseClassDef *bcdi;
+ const BaseClassDef *bcdi;
for (;(bcdi=bcli.current()) && prot!=Private;++bcli)
{
Protection baseProt = classInheritedProtectionLevel(bcdi->classDef,bcd,bcdi->prot,level+1);
@@ -3448,9 +3459,9 @@ static QCString stripDeclKeywords(const QCString &s)
}
// forward decl for circular dependencies
-static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type);
+static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCString type);
-QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec)
+QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec)
{
QCString templSpec = spec.stripWhiteSpace();
@@ -3471,7 +3482,7 @@ QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec
static QCString getCanonicalTypeForIdentifier(
- Definition *d,FileDef *fs,const QCString &word,
+ const Definition *d,const FileDef *fs,const QCString &word,
QCString *tSpec,int count=0)
{
if (count>10) return word; // oops recursion
@@ -3492,8 +3503,8 @@ static QCString getCanonicalTypeForIdentifier(
//printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n",
// word.data(),tSpec?tSpec->data():"<none>",templSpec.data());
- ClassDef *cd = 0;
- MemberDef *mType = 0;
+ const ClassDef *cd = 0;
+ const MemberDef *mType = 0;
QCString ts;
QCString resolvedType;
@@ -3607,7 +3618,7 @@ static QCString getCanonicalTypeForIdentifier(
return result;
}
-static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
+static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCString type)
{
type = type.stripWhiteSpace();
@@ -3677,7 +3688,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type)
return removeRedundantWhiteSpace(canType);
}
-static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument *arg)
+static QCString extractCanonicalArgType(const Definition *d,const FileDef *fs,const Argument *arg)
{
QCString type = arg->type.stripWhiteSpace();
QCString name = arg->name;
@@ -3701,8 +3712,8 @@ static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument
}
static bool matchArgument2(
- Definition *srcScope,FileDef *srcFileScope,Argument *srcA,
- Definition *dstScope,FileDef *dstFileScope,Argument *dstA
+ const Definition *srcScope,const FileDef *srcFileScope,Argument *srcA,
+ const Definition *dstScope,const FileDef *dstFileScope,Argument *dstA
)
{
//printf(">> match argument: %s::`%s|%s' (%s) <-> %s::`%s|%s' (%s)\n",
@@ -3762,10 +3773,9 @@ static bool matchArgument2(
// new algorithm for argument matching
-bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl,
- Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl,
- bool checkCV
- )
+bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl,
+ const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl,
+ bool checkCV)
{
//printf("*** matchArguments2\n");
ASSERT(srcScope!=0 && dstScope!=0);
@@ -3791,7 +3801,7 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr
{ // special case for finding match between func() and func(void)
Argument *a=new Argument;
a->type = "void";
- srcAl->append(a);
+ const_cast<ArgumentList*>(srcAl)->append(a);
MATCH
return TRUE;
}
@@ -3800,7 +3810,7 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr
{ // special case for finding match between func(void) and func()
Argument *a=new Argument;
a->type = "void";
- dstAl->append(a);
+ const_cast<ArgumentList*>(dstAl)->append(a);
MATCH
return TRUE;
}
@@ -3987,7 +3997,7 @@ void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl,bool forceNameOverwr
static void findMembersWithSpecificName(MemberName *mn,
const char *args,
bool checkStatics,
- FileDef *currentFile,
+ const FileDef *currentFile,
bool checkCV,
const char *forceTagFile,
QList<MemberDef> &members)
@@ -3995,11 +4005,11 @@ static void findMembersWithSpecificName(MemberName *mn,
//printf(" Function with global scope name `%s' args=`%s'\n",
// mn->memberName(),args);
MemberNameIterator mli(*mn);
- MemberDef *md;
+ const MemberDef *md = 0;
for (mli.toFirst();(md=mli.current());++mli)
{
- FileDef *fd=md->getFileDef();
- GroupDef *gd=md->getGroupDef();
+ const FileDef *fd=md->getFileDef();
+ const GroupDef *gd=md->getGroupDef();
//printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p current=%p ref=%s\n",
// md->name().data(),args,fd,gd,currentFile,md->getReference().data());
if (
@@ -4014,7 +4024,7 @@ static void findMembersWithSpecificName(MemberName *mn,
if (args && !md->isDefine() && qstrcmp(args,"()")!=0)
{
argList=new ArgumentList;
- ArgumentList *mdAl = md->argumentList();
+ const ArgumentList *mdAl = md->argumentList();
stringToArgumentList(args,argList);
match=matchArguments2(
md->getOuterScope(),fd,mdAl,
@@ -4056,13 +4066,13 @@ static void findMembersWithSpecificName(MemberName *mn,
bool getDefs(const QCString &scName,
const QCString &mbName,
const char *args,
- MemberDef *&md,
- ClassDef *&cd,
- FileDef *&fd,
- NamespaceDef *&nd,
- GroupDef *&gd,
+ const MemberDef *&md,
+ const ClassDef *&cd,
+ const FileDef *&fd,
+ const NamespaceDef *&nd,
+ const GroupDef *&gd,
bool forceEmptyScope,
- FileDef *currentFile,
+ const FileDef *currentFile,
bool checkCV,
const char *forceTagFile
)
@@ -4127,8 +4137,8 @@ bool getDefs(const QCString &scName,
className=mScope;
}
- MemberDef *tmd=0;
- ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd);
+ const MemberDef *tmd=0;
+ const ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd);
if (fcd==0 && className.find('<')!=-1) // try without template specifiers as well
{
QCString nameWithoutTemplates = stripTemplateSpecifiersFromScope(className,FALSE);
@@ -4225,7 +4235,7 @@ bool getDefs(const QCString &scName,
if (tmd && tmd->isEnumerate() && tmd->isStrong()) // scoped enum
{
//printf("Found scoped enum!\n");
- MemberList *tml = tmd->enumFieldList();
+ const MemberList *tml = tmd->enumFieldList();
if (tml)
{
MemberListIterator tmi(*tml);
@@ -4334,12 +4344,12 @@ bool getDefs(const QCString &scName,
// namespaceName.data(),mn->count());
bool found=FALSE;
MemberNameIterator mmli(*mn);
- MemberDef *mmd;
+ const MemberDef *mmd;
for (mmli.toFirst();((mmd=mmli.current()) && !found);++mmli)
{
//printf("mmd->getNamespaceDef()=%p fnd=%p\n",
// mmd->getNamespaceDef(),fnd);
- MemberDef *emd = mmd->getEnumScope();
+ const MemberDef *emd = mmd->getEnumScope();
if (emd && emd->isStrong())
{
//printf("yes match %s<->%s!\n",mScope.data(),emd->localName().data());
@@ -4358,14 +4368,14 @@ bool getDefs(const QCString &scName,
return FALSE;
}
}
- else if (mmd->getNamespaceDef()==fnd /* && mmd->isLinkable() */ )
+ else if (mmd->getOuterScope()==fnd /* && mmd->isLinkable() */ )
{ // namespace is found
bool match=TRUE;
ArgumentList *argList=0;
if (args && qstrcmp(args,"()")!=0)
{
argList=new ArgumentList;
- ArgumentList *mmdAl = mmd->argumentList();
+ const ArgumentList *mmdAl = mmd->argumentList();
stringToArgumentList(args,argList);
match=matchArguments2(
mmd->getOuterScope(),mmd->getFileDef(),mmdAl,
@@ -4398,7 +4408,7 @@ bool getDefs(const QCString &scName,
}
}
}
- if (found)
+ if (found)
{
if (!md->isLinkable())
{
@@ -4408,7 +4418,7 @@ bool getDefs(const QCString &scName,
}
else
{
- gd=md->getGroupDef();
+ gd=md->resolveAlias()->getGroupDef();
if (gd && gd->isLinkable()) nd=0; else gd=0;
return TRUE;
}
@@ -4421,7 +4431,7 @@ bool getDefs(const QCString &scName,
MemberDef *mmd;
for (mmli.toFirst();(mmd=mmli.current());++mmli)
{
- MemberDef *tmd = mmd->getEnumScope();
+ const MemberDef *tmd = mmd->getEnumScope();
//printf("try member %s tmd=%s\n",mmd->name().data(),tmd?tmd->name().data():"<none>");
int ni=namespaceName.findRev("::");
//printf("namespaceName=%s ni=%d\n",namespaceName.data(),ni);
@@ -4475,7 +4485,7 @@ bool getDefs(const QCString &scName,
//printf("member is linkable md->name()=`%s'\n",md->name().data());
fd=md->getFileDef();
gd=md->getGroupDef();
- MemberDef *tmd = md->getEnumScope();
+ const MemberDef *tmd = md->getEnumScope();
if (
(gd && gd->isLinkable()) || (fd && fd->isLinkable()) ||
(tmd && tmd->isStrong())
@@ -4602,10 +4612,10 @@ static bool isLowerCase(QCString &s)
bool resolveRef(/* in */ const char *scName,
/* in */ const char *name,
/* in */ bool inSeeBlock,
- /* out */ Definition **resContext,
- /* out */ MemberDef **resMember,
+ /* out */ const Definition **resContext,
+ /* out */ const MemberDef **resMember,
bool lookForSpecialization,
- FileDef *currentFile,
+ const FileDef *currentFile,
bool checkScope
)
{
@@ -4704,11 +4714,11 @@ bool resolveRef(/* in */ const char *scName,
QCString scopeStr=scName;
- MemberDef *md = 0;
- ClassDef *cd = 0;
- FileDef *fd = 0;
- NamespaceDef *nd = 0;
- GroupDef *gd = 0;
+ const MemberDef *md = 0;
+ const ClassDef *cd = 0;
+ const FileDef *fd = 0;
+ const NamespaceDef *nd = 0;
+ const GroupDef *gd = 0;
// check if nameStr is a member or global.
//printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n",
@@ -4876,7 +4886,7 @@ bool generateRef(OutputDocInterface &od,const char *scName,
bool resolveLink(/* in */ const char *scName,
/* in */ const char *lr,
/* in */ bool /*inSeeBlock*/,
- /* out */ Definition **resContext,
+ /* out */ const Definition **resContext,
/* out */ QCString &resAnchor
)
{
@@ -4885,12 +4895,12 @@ bool resolveLink(/* in */ const char *scName,
QCString linkRef=lr;
QCString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,FALSE);
//printf("ResolveLink linkRef=%s\n",lr);
- FileDef *fd;
- GroupDef *gd;
- PageDef *pd;
- ClassDef *cd;
- DirDef *dir;
- NamespaceDef *nd;
+ const FileDef *fd;
+ const GroupDef *gd;
+ const PageDef *pd;
+ const ClassDef *cd;
+ const DirDef *dir;
+ const NamespaceDef *nd;
SectionInfo *si=0;
bool ambig;
if (linkRef.isEmpty()) // no reference name!
@@ -4899,7 +4909,7 @@ bool resolveLink(/* in */ const char *scName,
}
else if ((pd=Doxygen::pageSDict->find(linkRef))) // link to a page
{
- GroupDef *gd = pd->getGroupDef();
+ const GroupDef *gd = pd->getGroupDef();
if (gd)
{
if (!pd->name().isEmpty()) si=Doxygen::sectionDict->find(pd->name());
@@ -4971,7 +4981,7 @@ bool resolveLink(/* in */ const char *scName,
}
else // probably a member reference
{
- MemberDef *md;
+ const MemberDef *md = 0;
bool res = resolveRef(scName,lr,TRUE,resContext,&md);
if (md) resAnchor=md->anchor();
return res;
@@ -4990,7 +5000,7 @@ bool generateLink(OutputDocInterface &od,const char *clName,
const char *lr,bool inSeeBlock,const char *lt)
{
//printf("generateLink(clName=%s,lr=%s,lr=%s)\n",clName,lr,lt);
- Definition *compound;
+ const Definition *compound = 0;
//PageDef *pageDef=0;
QCString anchor,linkText=linkToText(SrcLangExt_Unknown,lt,FALSE);
//printf("generateLink linkText=%s\n",linkText.data());
@@ -5002,7 +5012,7 @@ bool generateLink(OutputDocInterface &od,const char *clName,
compound->definitionType()==Definition::TypeGroup /* is group */
)
{
- linkText=(dynamic_cast<GroupDef *>(compound))->groupTitle(); // use group's title as link
+ linkText=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link
}
else if (compound->definitionType()==Definition::TypeFile)
{
@@ -5127,7 +5137,7 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig)
if (fn->count()==1)
{
FileDef *fd = fn->getFirst();
-#if defined(_WIN32) || defined(__MACOSX__) // Windows or MacOSX
+#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__) // Windows or MacOSX
bool isSamePath = fd->getPath().right(path.length()).lower()==path.lower();
#else // Unix
bool isSamePath = fd->getPath().right(path.length())==path;
@@ -5379,7 +5389,7 @@ static void initBaseClassHierarchy(BaseClassList *bcl)
}
//----------------------------------------------------------------------------
-bool classHasVisibleChildren(ClassDef *cd)
+bool classHasVisibleChildren(const ClassDef *cd)
{
BaseClassList *bcl;
@@ -5421,14 +5431,14 @@ void initClassHierarchy(ClassSDict *cl)
//----------------------------------------------------------------------------
-bool hasVisibleRoot(BaseClassList *bcl)
+bool hasVisibleRoot(const BaseClassList *bcl)
{
if (bcl)
{
BaseClassListIterator bcli(*bcl);
for ( ; bcli.current(); ++bcli)
{
- ClassDef *cd=bcli.current()->classDef;
+ const ClassDef *cd=bcli.current()->classDef;
if (cd->isVisibleInHierarchy()) return TRUE;
hasVisibleRoot(cd->baseClasses());
}
@@ -5473,10 +5483,12 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor
case '(': growBuf.addStr("_07"); break;
case ')': growBuf.addStr("_08"); break;
case '+': growBuf.addStr("_09"); break;
- case '=': growBuf.addStr("_0A"); break;
- case '$': growBuf.addStr("_0B"); break;
- case '\\': growBuf.addStr("_0C"); break;
- case '@': growBuf.addStr("_0D"); break;
+ case '=': growBuf.addStr("_0a"); break;
+ case '$': growBuf.addStr("_0b"); break;
+ case '\\': growBuf.addStr("_0c"); break;
+ case '@': growBuf.addStr("_0d"); break;
+ case ']': growBuf.addStr("_0e"); break;
+ case '[': growBuf.addStr("_0f"); break;
default:
if (c<0)
{
@@ -6154,7 +6166,7 @@ QCString getOverloadDocs()
void addMembersToMemberGroup(MemberList *ml,
MemberGroupSDict **ppMemberGroupSDict,
- Definition *context)
+ const Definition *context)
{
ASSERT(context!=0);
//printf("addMemberToMemberGroup()\n");
@@ -6166,7 +6178,7 @@ void addMembersToMemberGroup(MemberList *ml,
{
if (md->isEnumerate()) // insert enum value of this enum into groups
{
- MemberList *fmdl=md->enumFieldList();
+ const MemberList *fmdl=md->enumFieldList();
if (fmdl!=0)
{
MemberListIterator fmli(*fmdl);
@@ -6324,7 +6336,7 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri
QCString normalizeNonTemplateArgumentsInString(
const QCString &name,
- Definition *context,
+ const Definition *context,
const ArgumentList * formalArgs)
{
// skip until <
@@ -6344,7 +6356,7 @@ QCString normalizeNonTemplateArgumentsInString(
if (formalArgs) // check that n is not a formal template argument
{
ArgumentListIterator formAli(*formalArgs);
- Argument *formArg;
+ const Argument *formArg;
for (formAli.toFirst();
(formArg=formAli.current()) && !found;
++formAli
@@ -6356,7 +6368,7 @@ QCString normalizeNonTemplateArgumentsInString(
if (!found)
{
// try to resolve the type
- ClassDef *cd = getResolvedClass(context,0,n);
+ const ClassDef *cd = getResolvedClass(context,0,n);
if (cd)
{
result+=cd->name();
@@ -6656,7 +6668,7 @@ found:
PageDef *addRelatedPage(const char *name,const QCString &ptitle,
const QCString &doc,
- QList<SectionInfo> * /*anchors*/,
+ const QList<SectionInfo> * /*anchors*/,
const char *fileName,int startLine,
const QList<ListItemInfo> *sli,
GroupDef *gd,
@@ -6782,7 +6794,7 @@ void addRefItem(const QList<ListItemInfo> *sli,
}
}
-bool recursivelyAddGroupListToTitle(OutputList &ol,Definition *d,bool root)
+bool recursivelyAddGroupListToTitle(OutputList &ol,const Definition *d,bool root)
{
GroupList *groups = d->partOfGroups();
if (groups) // write list of group to which this definition belongs
@@ -6815,7 +6827,7 @@ bool recursivelyAddGroupListToTitle(OutputList &ol,Definition *d,bool root)
return false;
}
-void addGroupListToTitle(OutputList &ol,Definition *d)
+void addGroupListToTitle(OutputList &ol,const Definition *d)
{
recursivelyAddGroupListToTitle(ol,d,TRUE);
}
@@ -7077,6 +7089,7 @@ QCString latexFilterURL(const char *s)
switch (c)
{
case '#': t << "\\#"; break;
+ case '%': t << "\\%"; break;
default:
t << c;
break;
@@ -7200,7 +7213,7 @@ bool findAndRemoveWord(QCString &s,const QCString &word)
{
if (i>0 && isspace((uchar)s.at(i-1)))
i--,l++;
- else if (i+l<(int)s.length() && isspace(s.at(i+l)))
+ else if (i+l<(int)s.length() && isspace((uchar)s.at(i+l)))
l++;
s = s.left(i)+s.mid(i+l); // remove word + spacing
return TRUE;
@@ -7412,27 +7425,31 @@ void addCodeOnlyMappings()
SrcLangExt getLanguageFromFileName(const QCString& fileName)
{
- int i = fileName.findRev('.');
- if (i!=-1) // name has an extension
- {
- QCString extStr=fileName.right(fileName.length()-i).lower();
- if (!extStr.isEmpty()) // non-empty extension
+ QFileInfo fi(fileName);
+ QCString extName = fi.extension().lower().data();
+ if (extName.isEmpty()) extName=".no_extension";
+ if (extName.at(0)!='.') extName.prepend(".");
+ int *pVal=g_extLookup.find(extName.data());
+ if (pVal) // listed extension
{
- int *pVal=g_extLookup.find(extStr);
- if (pVal) // listed extension
- {
- //printf("getLanguageFromFileName(%s)=%x\n",extStr.data(),*pVal);
- return (SrcLangExt)*pVal;
- }
+ //printf("getLanguageFromFileName(%s)=%x\n",fi.extension().data(),*pVal);
+ return (SrcLangExt)*pVal;
}
- }
//printf("getLanguageFromFileName(%s) not found!\n",fileName.data());
return SrcLangExt_Cpp; // not listed => assume C-ish language.
}
+QCString getFileNameExtension(QCString fn)
+{
+ if (fn.isEmpty()) return "";
+ int lastDot = fn.findRev('.');
+ if (lastDot!=-1) return fn.mid(lastDot);
+ return "";
+}
+
//--------------------------------------------------------------------------
-MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope,
+MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope,
const char *n)
{
if (scope==0 ||
@@ -7504,7 +7521,7 @@ MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope,
}
/*! Returns true iff the given name string appears to be a typedef in scope. */
-bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n)
+bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n)
{
MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n);
@@ -7931,12 +7948,12 @@ QCString expandAlias(const QCString &aliasName,const QCString &aliasValue)
return result;
}
-void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al)
+void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList *al)
{
if (al==0) return;
ol.startConstraintList(theTranslator->trTypeConstraints());
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
for (;(a=ali.current());++ali)
{
ol.startConstraintParam();
@@ -8136,7 +8153,7 @@ bool patternMatch(const QFileInfo &fi,const QStrList *patList)
bool found = FALSE;
// For Windows/Mac, always do the case insensitive match
-#if defined(_WIN32) || defined(__MACOSX__)
+#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__)
caseSenseNames = FALSE;
#endif
@@ -8452,16 +8469,20 @@ QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope)
return "::";
}
}
-
+/** Checks whether the given url starts with a supported protocol */
+bool isURL(const QCString &url)
+{
+ QCString loc_url = url.stripWhiteSpace();
+ return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" ||
+ loc_url.left(4)=="ftp:" || loc_url.left(5)=="file:";
+}
/** Corrects URL \a url according to the relative path \a relPath.
* Returns the corrected URL. For absolute URLs no correction will be done.
*/
QCString correctURL(const QCString &url,const QCString &relPath)
{
QCString result = url;
- if (!relPath.isEmpty() &&
- url.left(5)!="http:" && url.left(6)!="https:" &&
- url.left(4)!="ftp:" && url.left(5)!="file:")
+ if (!relPath.isEmpty() && !isURL(url))
{
result.prepend(relPath);
}
@@ -8549,7 +8570,7 @@ QCString stripIndentation(const QCString &s)
}
-bool fileVisibleInIndex(FileDef *fd,bool &genSourceFile)
+bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile)
{
static bool allExternals = Config_getBool(ALLEXTERNALS);
bool isDocFile = fd->isDocumentationFile();
@@ -8668,12 +8689,12 @@ uint getUtf8CodeToUpper( const QCString& s, int idx )
//--------------------------------------------------------------------------------------
-bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct)
+bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct)
{
if (nd->getNamespaceSDict())
{
NamespaceSDict::Iterator cnli(*nd->getNamespaceSDict());
- NamespaceDef *cnd;
+ const NamespaceDef *cnd;
for (cnli.toFirst();(cnd=cnli.current());++cnli)
{
if (cnd->isLinkableInProject() && cnd->localName().find('@')==-1)
@@ -8688,7 +8709,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl
}
if (includeClasses)
{
- ClassSDict *d = nd->getClassSDict();
+ const ClassSDict *d = nd->getClassSDict();
if (filterClasses)
{
if (ct == ClassDef::Interface)
@@ -8708,7 +8729,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl
if (d)
{
ClassSDict::Iterator cli(*d);
- ClassDef *cd;
+ const ClassDef *cd;
for (;(cd=cli.current());++cli)
{
if (cd->isLinkableInProject() && cd->templateMaster()==0)
@@ -8723,7 +8744,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl
//----------------------------------------------------------------------------
-bool classVisibleInIndex(ClassDef *cd)
+bool classVisibleInIndex(const ClassDef *cd)
{
static bool allExternals = Config_getBool(ALLEXTERNALS);
return (allExternals && cd->isLinkable()) || cd->isLinkableInProject();
diff --git a/src/util.h b/src/util.h
index 31691af..ad062d0 100644
--- a/src/util.h
+++ b/src/util.h
@@ -142,13 +142,13 @@ QCString dateToString(bool);
bool getDefs(const QCString &scopeName,
const QCString &memberName,
const char *,
- MemberDef *&md,
- ClassDef *&cd,
- FileDef *&fd,
- NamespaceDef *&nd,
- GroupDef *&gd,
+ const MemberDef *&md,
+ const ClassDef *&cd,
+ const FileDef *&fd,
+ const NamespaceDef *&nd,
+ const GroupDef *&gd,
bool forceEmptyScope=FALSE,
- FileDef *currentFile=0,
+ const FileDef *currentFile=0,
bool checkCV=FALSE,
const char *forceTagFile=0
);
@@ -158,17 +158,17 @@ QCString getFileFilter(const char* name,bool isSourceCode);
bool resolveRef(/* in */ const char *scName,
/* in */ const char *name,
/* in */ bool inSeeBlock,
- /* out */ Definition **resContext,
- /* out */ MemberDef **resMember,
+ /* out */ const Definition **resContext,
+ /* out */ const MemberDef **resMember,
/* in */ bool lookForSpecializations = TRUE,
- /* in */ FileDef *currentFile = 0,
+ /* in */ const FileDef *currentFile = 0,
/* in */ bool checkScope = FALSE
);
bool resolveLink(/* in */ const char *scName,
/* in */ const char *lr,
/* in */ bool inSeeBlock,
- /* out */ Definition **resContext,
+ /* out */ const Definition **resContext,
/* out */ QCString &resAnchor
);
@@ -183,10 +183,10 @@ void generateFileRef(OutputDocInterface &od,const char *,
void writePageRef(OutputDocInterface &od,const char *cn,const char *mn);
-QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec);
+QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec);
-bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl,
- Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl,
+bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl,
+ const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl,
bool checkCV
);
@@ -206,10 +206,10 @@ QCString resolveDefines(const char *n);
ClassDef *getClass(const char *key);
-ClassDef *getResolvedClass(const Definition *scope,
+const ClassDef *getResolvedClass(const Definition *scope,
const FileDef *fileScope,
const char *key,
- MemberDef **pTypeDef=0,
+ const MemberDef **pTypeDef=0,
QCString *pTemplSpec=0,
bool mayBeUnlinkable=FALSE,
bool mayBeHidden=FALSE,
@@ -231,9 +231,9 @@ inline bool isId(int c)
QCString removeRedundantWhiteSpace(const QCString &s);
-QCString argListToString(ArgumentList *al,bool useCanonicalType=FALSE,bool showDefVals=TRUE);
+QCString argListToString(const ArgumentList *al,bool useCanonicalType=FALSE,bool showDefVals=TRUE);
-QCString tempArgListToString(ArgumentList *al,SrcLangExt lang);
+QCString tempArgListToString(const ArgumentList *al,SrcLangExt lang);
QCString generateMarker(int id);
@@ -260,13 +260,13 @@ QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0);
void initClassHierarchy(ClassSDict *cl);
-bool hasVisibleRoot(BaseClassList *bcl);
-bool classHasVisibleChildren(ClassDef *cd);
-bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct);
-bool classVisibleInIndex(ClassDef *cd);
+bool hasVisibleRoot(const BaseClassList *bcl);
+bool classHasVisibleChildren(const ClassDef *cd);
+bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct);
+bool classVisibleInIndex(const ClassDef *cd);
int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level=0);
-Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection prot=Public,int level=0);
+Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot=Public,int level=0);
QCString convertNameToFile(const char *name,bool allowDots=FALSE,bool allowUnderscore=FALSE);
@@ -292,16 +292,16 @@ QCString convertToJSString(const char *s, bool applyTextDir = true);
QCString getOverloadDocs();
-void addMembersToMemberGroup(/* in */ MemberList *ml,
+void addMembersToMemberGroup(/* in,out */ MemberList *ml,
/* in,out */ MemberGroupSDict **ppMemberGroupSDict,
- /* in */ Definition *context);
+ /* in */ const Definition *context);
int extractClassNameFromType(const QCString &type,int &pos,
QCString &name,QCString &templSpec,SrcLangExt=SrcLangExt_Unknown);
QCString normalizeNonTemplateArgumentsInString(
const QCString &name,
- Definition *context,
+ const Definition *context,
const ArgumentList *formalArgs);
QCString substituteTemplateArgumentsInString(
@@ -315,8 +315,8 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName,
bool parentOnly=TRUE,
QCString *lastScopeStripped=0);
-QCString resolveTypeDef(Definition *d,const QCString &name,
- Definition **typedefContext=0);
+QCString resolveTypeDef(const Definition *d,const QCString &name,
+ const Definition **typedefContext=0);
QCString mergeScopes(const QCString &leftScope,const QCString &rightScope);
@@ -328,18 +328,20 @@ void addRefItem(const QList<ListItemInfo> *sli,const char *prefix,
const char *key,
const char *name,const char *title,const char *args,Definition *scope);
-PageDef *addRelatedPage(const char *name,const QCString &ptitle,
- const QCString &doc,QList<SectionInfo> *anchors,
- const char *fileName,int startLine,
- const QList<ListItemInfo> *sli,
- GroupDef *gd=0,
- TagInfo *tagInfo=0,
- SrcLangExt lang=SrcLangExt_Unknown
- );
+PageDef *addRelatedPage(const char *name,
+ const QCString &ptitle,
+ const QCString &doc,
+ const QList<SectionInfo> *anchors,
+ const char *fileName,int startLine,
+ const QList<ListItemInfo> *sli,
+ GroupDef *gd=0,
+ TagInfo *tagInfo=0,
+ SrcLangExt lang=SrcLangExt_Unknown
+ );
QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore=FALSE);
-void addGroupListToTitle(OutputList &ol,Definition *d);
+void addGroupListToTitle(OutputList &ol,const Definition *d);
void filterLatexString(FTextStream &t,const char *str,
bool insideTabbing=FALSE,
@@ -385,23 +387,22 @@ bool findAndRemoveWord(QCString &s,const QCString &word);
QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine);
-//void stringToSearchIndex(const QCString &docUrlBase,const QCString &title,
-// const QCString &str, bool priority=FALSE,
-// const QCString &anchor="");
-
bool updateLanguageMapping(const QCString &extension,const QCString &parser);
SrcLangExt getLanguageFromFileName(const QCString& fileName);
+QCString getFileNameExtension(QCString fn);
void initDefaultExtensionMapping();
void addCodeOnlyMappings();
-MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope,
+MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope,
const char *n);
-bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n);
+bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n);
-ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md,
- MemberDef **pMemType=0,QCString *pTemplSpec=0,
- QCString *pResolvedType=0,
- ArgumentList *actTemplParams=0);
+const ClassDef *newResolveTypedef(const FileDef *fileScope,
+ const MemberDef *md,
+ const MemberDef **pMemType=0,
+ QCString *pTemplSpec=0,
+ QCString *pResolvedType=0,
+ ArgumentList *actTemplParams=0);
QCString parseCommentAsText(const Definition *scope,const MemberDef *member,const QCString &doc,const QCString &fileName,int lineNr);
@@ -418,7 +419,7 @@ int countAliasArguments(const QCString argList);
QCString resolveAliasCmd(const QCString aliasCmd);
QCString expandAlias(const QCString &aliasName,const QCString &aliasValue);
-void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al);
+void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList *al);
QCString convertCharEntitiesToUTF8(const QCString &s);
@@ -453,6 +454,8 @@ bool copyFile(const QCString &src,const QCString &dest);
QCString extractBlock(const QCString text,const QCString marker);
int lineBlock(const QCString text,const QCString marker);
+bool isURL(const QCString &url);
+
QCString correctURL(const QCString &url,const QCString &relPath);
QCString processMarkup(const QCString &s);
@@ -463,7 +466,7 @@ QCString stripIndentation(const QCString &s);
QCString getDotImageExtension(void);
-bool fileVisibleInIndex(FileDef *fd,bool &genSourceFile);
+bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile);
void addDocCrossReference(MemberDef *src,MemberDef *dst);
diff --git a/src/vhdlcode.h b/src/vhdlcode.h
index e21ddea..a7b4687 100644
--- a/src/vhdlcode.h
+++ b/src/vhdlcode.h
@@ -8,7 +8,7 @@ class MemberDef;
void parseVhdlCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs);
void resetVhdlCodeParserState();
void codeFreeVhdlScanner();
diff --git a/src/vhdlcode.l b/src/vhdlcode.l
index 9e296cc..7c6cfa4 100644
--- a/src/vhdlcode.l
+++ b/src/vhdlcode.l
@@ -86,7 +86,7 @@ static int g_inputPosition; //!< read offset during parsing
static int g_inputLines; //!< number of line in the code fragment
static int g_yyLineNr; //!< current line number
static bool g_needsTermination;
-static Definition *g_searchCtx;
+static const Definition *g_searchCtx;
static bool g_exampleBlock;
static QCString g_exampleName;
@@ -430,13 +430,13 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol,
}
}
-static void setParameterList(MemberDef *md)
+static void setParameterList(const MemberDef *md)
{
g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : "";
- ArgumentList *al = md->argumentList();
+ const ArgumentList *al = md->argumentList();
if (al==0) return;
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
g_parmName = a->name.copy();
@@ -1543,7 +1543,7 @@ void resetVhdlCodeParserState()
void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString &s,
bool exBlock, const char *exName,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool,Definition *searchCtx,
+ const MemberDef *memberDef,bool,const Definition *searchCtx,
bool /* collectXRefs */)
{
//printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
@@ -1551,7 +1551,7 @@ void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString
printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
if (memberDef)
{
- ClassDef *dd=memberDef->getClassDef();
+ const ClassDef *dd=memberDef->getClassDef();
if (dd) g_CurrClass=dd->name();
}
resetVhdlCodeParserState();
diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp
index e70f099..bba249a 100644
--- a/src/vhdldocgen.cpp
+++ b/src/vhdldocgen.cpp
@@ -1730,8 +1730,8 @@ QCString VhdlDocGen::convertArgumentListToString(const ArgumentList* al,bool fun
}
-void VhdlDocGen::writeVhdlDeclarations(MemberList* ml,
- OutputList& ol,GroupDef* gd,ClassDef* cd,FileDef *fd,NamespaceDef* nd)
+void VhdlDocGen::writeVhdlDeclarations(const MemberList* ml,
+ OutputList& ol,const GroupDef* gd,const ClassDef* cd,const FileDef *fd,const NamespaceDef* nd)
{
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::LIBRARY,FALSE),0,FALSE,VhdlDocGen::LIBRARY);
VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::USE,FALSE),0,FALSE,VhdlDocGen::USE);
@@ -1761,36 +1761,49 @@ void VhdlDocGen::writeVhdlDeclarations(MemberList* ml,
}
-static void setGlobalType(MemberList *ml)
+void VhdlDocGen::correctMemberProperties(MemberDef *md)
{
- if (ml==0) return;
- MemberDef *mdd=0;
- MemberListIterator mmli(*ml);
- for ( ; (mdd=mmli.current()); ++mmli )
+ if (qstrcmp(md->argsString(),"package")==0)
{
- if (qstrcmp(mdd->argsString(),"package")==0)
- {
- mdd->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
- }
- else if (qstrcmp(mdd->argsString(),"configuration")==0)
- {
- mdd->setMemberSpecifiers(VhdlDocGen::CONFIG);
- }
- else if (qstrcmp(mdd->typeString(),"library")==0)
- {
- mdd->setMemberSpecifiers(VhdlDocGen::LIBRARY);
- }
- else if (qstrcmp(mdd->typeString(),"use")==0)
- {
- mdd->setMemberSpecifiers(VhdlDocGen::USE);
- }
- else if (qstricmp(mdd->typeString(),"misc")==0)
+ md->setMemberSpecifiers(VhdlDocGen::INSTANTIATION);
+ }
+ else if (qstrcmp(md->argsString(),"configuration")==0)
+ {
+ md->setMemberSpecifiers(VhdlDocGen::CONFIG);
+ }
+ else if (qstrcmp(md->typeString(),"library")==0)
+ {
+ md->setMemberSpecifiers(VhdlDocGen::LIBRARY);
+ }
+ else if (qstrcmp(md->typeString(),"use")==0)
+ {
+ md->setMemberSpecifiers(VhdlDocGen::USE);
+ }
+ else if (qstricmp(md->typeString(),"misc")==0)
+ {
+ md->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS);
+ }
+ else if (qstricmp(md->typeString(),"ucf_const")==0)
+ {
+ md->setMemberSpecifiers(VhdlDocGen::UCF_CONST);
+ }
+
+ if (md->getMemberSpecifiers()==VhdlDocGen::UCF_CONST)
+ {
+ int mm=md->name().findRev('_');
+ if (mm>0)
{
- mdd->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS);
+ md->setName(md->name().left(mm));
}
- else if (qstricmp(mdd->typeString(),"ucf_const")==0)
+ }
+ else if (md->getMemberSpecifiers()==VhdlDocGen::TYPE)
+ {
+ QCString largs=md->argsString();
+ bool bRec=largs.stripPrefix("record") ;
+ bool bUnit=largs.stripPrefix("units") ;
+ if (bRec || bUnit)
{
- mdd->setMemberSpecifiers(VhdlDocGen::UCF_CONST);
+ md->setType("");
}
}
}
@@ -1924,11 +1937,11 @@ void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile)
/* writes a vhdl type declaration */
-void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
bool /*inGroup*/)
{
- Definition *d=0;
+ const Definition *d=0;
ASSERT(cd!=0 || nd!=0 || fd!=0 || gd!=0 ||
mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY ||
@@ -1987,14 +2000,9 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
/*VHDL CHANGE */
bool bRec,bUnit;
QCString ltype(mdef->typeString());
- // ltype=ltype.replace(reg," ");
QCString largs(mdef->argsString());
- // largs=largs.replace(reg," ");
- mdef->setType(ltype.data());
- mdef->setArgsString(largs.data());
- //ClassDef * plo=mdef->getClassDef();
ClassDef *kl=0;
- ArgumentList *alp = mdef->argumentList();
+ const ArgumentList *alp = mdef->argumentList();
QCString nn;
//VhdlDocGen::adjustRecordMember(mdef);
if (gd) gd=0;
@@ -2153,11 +2161,6 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
}
break;
case VhdlDocGen::UCF_CONST:
- mm=mdef->name().findRev('_');
- if (mm>0)
- {
- mdef->setName(mdef->name().left(mm));
- }
writeUCFLink(mdef,ol);
break;
case VhdlDocGen::SIGNAL:
@@ -2198,7 +2201,6 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
if (bRec || bUnit)
{
writeRecorUnit(largs,ol,mdef);
- mdef->setType("");
}
ol.endBold();
break;
@@ -2260,8 +2262,8 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
void VhdlDocGen::writePlainVHDLDeclarations(
- MemberList* mlist,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier)
+ const MemberList* mlist,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,int specifier)
{
SDict<QCString> pack(1009);
@@ -2292,7 +2294,7 @@ void VhdlDocGen::writePlainVHDLDeclarations(
pack.clear();
}//plainDeclaration
-static bool membersHaveSpecificType(MemberList *ml,uint64 type)
+static bool membersHaveSpecificType(const MemberList *ml,uint64 type)
{
if (ml==0) return FALSE;
MemberDef *mdd=0;
@@ -2320,11 +2322,10 @@ static bool membersHaveSpecificType(MemberList *ml,uint64 type)
return FALSE;
}
-void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
const char *title,const char *subtitle,bool /*showEnumValues*/,int type)
{
- setGlobalType(ml);
if (!membersHaveSpecificType(ml,type)) return;
if (title)
@@ -2377,7 +2378,7 @@ void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol,
}// writeVHDLDeclarations
-bool VhdlDocGen::writeClassType( ClassDef *& cd,
+bool VhdlDocGen::writeClassType( const ClassDef * cd,
OutputList &ol ,QCString & cname)
{
int id=cd->protection();
@@ -2398,7 +2399,7 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList&
{
if (mdef)
{
- ClassDef *cd=mdef->getClassDef();
+ const ClassDef *cd=mdef->getClassDef();
if (cd)
{
QCString n=cd->name();
@@ -2418,7 +2419,7 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList&
-void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname)
+void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname)
{
ParserInterface *pIntf = Doxygen::parserManager->getParser(".vhd");
// pIntf->resetCodeParserState();
@@ -2452,7 +2453,7 @@ void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname)
SrcLangExt_VHDL, // lang
FALSE, // isExample
0, // exampleName
- mdef->getFileDef(), // fileDef
+ const_cast<FileDef*>(mdef->getFileDef()), // fileDef
mdef->getStartBodyLine(), // startLine
mdef->getEndBodyLine(), // endLine
TRUE, // inlineFragment
@@ -3091,7 +3092,7 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int
BaseClassListIterator bcli(*cd->subClasses());
for ( ; bcli.current() && !found ; ++bcli)
{
- ClassDef *ccd=bcli.current()->classDef;
+ const ClassDef *ccd=bcli.current()->classDef;
if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster();
//printf("isSubClass() subclass %s\n",ccd->name().data());
if (ccd==scd)
@@ -3178,7 +3179,7 @@ void VhdlDocGen::createFlowChart(const MemberDef *mdef)
int actualStart= mdef->getStartBodyLine();
int actualEnd=mdef->getEndBodyLine();
- FileDef* fd=mdef->getFileDef();
+ const FileDef* fd=mdef->getFileDef();
bool b=readCodeFragment( fd->absFilePath().data(), actualStart,actualEnd,codeFragment);
if (!b) return;
@@ -4374,9 +4375,9 @@ void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf,
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *memberDef,
+ const MemberDef *memberDef,
bool showLineNumbers,
- Definition *searchCtx,
+ const Definition *searchCtx,
bool collectXRefs
)
{
diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h
index 9dd8417..e2c843c 100644
--- a/src/vhdldocgen.h
+++ b/src/vhdldocgen.h
@@ -163,20 +163,21 @@ class VhdlDocGen
static bool writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition* d, OutputList &ol);
- static void writeVhdlDeclarations(MemberList*,OutputList&,GroupDef*,ClassDef*,FileDef*,NamespaceDef*);
+ static void writeVhdlDeclarations(const MemberList*,OutputList&,const GroupDef*,const ClassDef*,const FileDef*,const NamespaceDef*);
- static void writeVHDLDeclaration(MemberDef* mdef,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+ static void writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
bool inGroup);
- static void writePlainVHDLDeclarations(MemberList* ml,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier);
+ static void writePlainVHDLDeclarations(const MemberList* ml,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
+ int specifier);
- static void writeVHDLDeclarations(MemberList* ml,OutputList &ol,
- ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
+ static void writeVHDLDeclarations(const MemberList* ml,OutputList &ol,
+ const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,
const char *title,const char *subtitle,bool showEnumValues,int type);
- static bool writeClassType(ClassDef *&,OutputList &ol ,QCString & cname);
+ static bool writeClassType(const ClassDef *,OutputList &ol ,QCString & cname);
static QCString convertArgumentListToString(const ArgumentList* al,bool f);
static QCString getProcessNumber();
@@ -192,8 +193,9 @@ class VhdlDocGen
static ClassDef* findArchitecture(const ClassDef *cd);
static ClassDef* findArchitecture(QCString identifier, QCString entity_name);
+ static void correctMemberProperties(MemberDef *md);
- static void writeSource(MemberDef *mdef,OutputList& ol,QCString & cname);
+ static void writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname);
static void writeAlphbeticalClass(OutputList& ol,const ClassDef* cd,const QCString &);
static QCString parseForConfig(QCString & entity,QCString & arch);
diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp
index 4a312bd..aeed048 100644
--- a/src/vhdljjparser.cpp
+++ b/src/vhdljjparser.cpp
@@ -146,7 +146,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En
oldEntry = 0;
VhdlParser::current=new Entry();
VhdlParser::initEntry(VhdlParser::current);
- groupEnterFile(fileName,yyLineNr);
+ Doxygen::docGroup.enterFile(fileName,yyLineNr);
vhdlFileName = fileName;
lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h
VhdlParserIF::parseVhdlfile(fileBuf,inLine);
@@ -193,7 +193,7 @@ void VhdlParser::initEntry(Entry *e)
e->fileName = yyFileName;
e->lang = SrcLangExt_VHDL;
isVhdlDocPending();
- initGroupInfo(e);
+ Doxygen::docGroup.initGroupInfo(e);
}
void VhdlParser::newEntry()
diff --git a/src/vhdljjparser.h b/src/vhdljjparser.h
index 3a2ed61..fffea47 100644
--- a/src/vhdljjparser.h
+++ b/src/vhdljjparser.h
@@ -59,9 +59,9 @@ class VHDLLanguageScanner : public ParserInterface
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
);
bool needsPreprocessing(const QCString &) { return TRUE; }
diff --git a/src/xmlcode.h b/src/xmlcode.h
index 5a9c78c..e463866 100644
--- a/src/xmlcode.h
+++ b/src/xmlcode.h
@@ -30,7 +30,7 @@ class Definition;
extern void parseXmlCode(CodeOutputInterface &,const char *,const QCString &,
bool ,const char *,FileDef *fd,
int startLine,int endLine,bool inlineFragment,
- MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx,
+ const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx,
bool collectXRefs);
extern void resetXmlCodeParserState();
diff --git a/src/xmlcode.l b/src/xmlcode.l
index c9529d6..42218b1 100644
--- a/src/xmlcode.l
+++ b/src/xmlcode.l
@@ -35,6 +35,7 @@
#include "config.h"
#include "filedef.h"
#include "tooltip.h"
+#include "message.h"
#define YY_NEVER_INTERACTIVE 1
#define YY_NO_INPUT 1
@@ -49,7 +50,7 @@ static int g_inputPosition; //!< read offset during parsing
static int g_inputLines; //!< number of line in the code fragment
static int g_yyLineNr; //!< current line number
static bool g_needsTermination;
-static Definition *g_searchCtx;
+static const Definition *g_searchCtx;
static bool g_exampleBlock;
static QCString g_exampleName;
@@ -332,12 +333,13 @@ void parseXmlCode(
int startLine,
int endLine,
bool inlineFragment,
- MemberDef *,
- bool,Definition *searchCtx,
+ const MemberDef *,
+ bool,const Definition *searchCtx,
bool /*collectXRefs*/
)
{
if (s.isEmpty()) return;
+ printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
g_code = &od;
g_inputString = s;
@@ -393,6 +395,7 @@ void parseXmlCode(
g_sourceFileDef=0;
}
+ printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
return;
}
diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp
index 1005719..c8d23a8 100644
--- a/src/xmldocvisitor.cpp
+++ b/src/xmldocvisitor.cpp
@@ -415,20 +415,22 @@ void XmlDocVisitor::visit(DocIncOperator *op)
pushEnabled();
m_hide = TRUE;
}
- SrcLangExt langExt = getLanguageFromFileName(m_langExt);
+ QCString locLangExt = getFileNameExtension(op->includeFileName());
+ if (locLangExt.isEmpty()) locLangExt = m_langExt;
+ SrcLangExt langExt = getLanguageFromFileName(locLangExt);
if (op->type()!=DocIncOperator::Skip)
{
popEnabled();
if (!m_hide)
{
- FileDef *fd;
+ FileDef *fd = 0;
if (!op->includeFileName().isEmpty())
{
QFileInfo cfi( op->includeFileName() );
fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() );
}
- Doxygen::parserManager->getParser(m_langExt)
+ Doxygen::parserManager->getParser(locLangExt)
->parseCode(m_ci,op->context(),
op->text(),langExt,op->isExample(),
op->exampleFile(),
@@ -1078,18 +1080,6 @@ void XmlDocVisitor::visitPost(DocInternalRef *)
m_t << " ";
}
-void XmlDocVisitor::visitPre(DocCopy *c)
-{
- if (m_hide) return;
- m_t << "<copydoc link=\"" << convertToXML(c->link()) << "\">";
-}
-
-void XmlDocVisitor::visitPost(DocCopy *)
-{
- if (m_hide) return;
- m_t << "</copydoc>" << endl;
-}
-
void XmlDocVisitor::visitPre(DocText *)
{
}
diff --git a/src/xmldocvisitor.h b/src/xmldocvisitor.h
index c2c6537..6fa1392 100644
--- a/src/xmldocvisitor.h
+++ b/src/xmldocvisitor.h
@@ -130,8 +130,6 @@ class XmlDocVisitor : public DocVisitor
void visitPost(DocXRefItem *);
void visitPre(DocInternalRef *);
void visitPost(DocInternalRef *);
- void visitPre(DocCopy *);
- void visitPost(DocCopy *);
void visitPre(DocText *);
void visitPost(DocText *);
void visitPre(DocHtmlBlockQuote *);
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp
index d3b8355..16abbf2 100644
--- a/src/xmlgen.cpp
+++ b/src/xmlgen.cpp
@@ -29,6 +29,8 @@
#include "defargs.h"
#include "outputgen.h"
#include "dot.h"
+#include "dotclassgraph.h"
+#include "dotincldepgraph.h"
#include "pagedef.h"
#include "filename.h"
#include "version.h"
@@ -336,10 +338,10 @@ void XMLCodeGenerator::finish()
if (m_insideCodeLine) endCodeLine();
}
-static void writeTemplateArgumentList(ArgumentList *al,
+static void writeTemplateArgumentList(const ArgumentList *al,
FTextStream &t,
- Definition *scope,
- FileDef *fileScope,
+ const Definition *scope,
+ const FileDef *fileScope,
int indent)
{
QCString indentStr;
@@ -348,7 +350,7 @@ static void writeTemplateArgumentList(ArgumentList *al,
{
t << indentStr << "<templateparamlist>" << endl;
ArgumentListIterator ali(*al);
- Argument *a;
+ const Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
t << indentStr << " <param>" << endl;
@@ -381,16 +383,16 @@ static void writeTemplateArgumentList(ArgumentList *al,
}
}
-static void writeMemberTemplateLists(MemberDef *md,FTextStream &t)
+static void writeMemberTemplateLists(const MemberDef *md,FTextStream &t)
{
- ArgumentList *templMd = md->templateArguments();
+ const ArgumentList *templMd = md->templateArguments();
if (templMd) // function template prefix
{
writeTemplateArgumentList(templMd,t,md->getClassDef(),md->getFileDef(),8);
}
}
-static void writeTemplateList(ClassDef *cd,FTextStream &t)
+static void writeTemplateList(const ClassDef *cd,FTextStream &t)
{
writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4);
}
@@ -398,8 +400,8 @@ static void writeTemplateList(ClassDef *cd,FTextStream &t)
static void writeXMLDocBlock(FTextStream &t,
const QCString &fileName,
int lineNr,
- Definition *scope,
- MemberDef * md,
+ const Definition *scope,
+ const MemberDef * md,
const QCString &text)
{
QCString stext = text.stripWhiteSpace();
@@ -442,7 +444,7 @@ void writeXMLCodeBlock(FTextStream &t,FileDef *fd)
delete xmlGen;
}
-static void writeMemberReference(FTextStream &t,Definition *def,MemberDef *rmd,const char *tagName)
+static void writeMemberReference(FTextStream &t,const Definition *def,const MemberDef *rmd,const char *tagName)
{
QCString scope = rmd->getScopeString();
QCString name = rmd->name();
@@ -478,7 +480,7 @@ static void stripQualifiers(QCString &typeStr)
}
}
-static QCString classOutputFileBase(ClassDef *cd)
+static QCString classOutputFileBase(const ClassDef *cd)
{
//static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
//if (inlineGroupedClasses && cd->partOfGroups()!=0)
@@ -487,7 +489,7 @@ static QCString classOutputFileBase(ClassDef *cd)
// return cd->getOutputFileBase();
}
-static QCString memberOutputFileBase(MemberDef *md)
+static QCString memberOutputFileBase(const MemberDef *md)
{
//static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
//if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0)
@@ -498,7 +500,7 @@ static QCString memberOutputFileBase(MemberDef *md)
}
-static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,Definition *def)
+static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream &t,const Definition *def)
{
// + declaration/definition arg lists
@@ -589,7 +591,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
if (isFunc)
{
- ArgumentList *al = md->argumentList();
+ const ArgumentList *al = md->argumentList();
t << " const=\"";
if (al!=0 && al->constSpecifier) t << "yes"; else t << "no";
t << "\"";
@@ -817,7 +819,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
t << " <bitfield>" << convertToXML(bitfield) << "</bitfield>" << endl;
}
- MemberDef *rmd = md->reimplements();
+ const MemberDef *rmd = md->reimplements();
if (rmd)
{
t << " <reimplements refid=\""
@@ -838,13 +840,13 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
if (isFunc) //function
{
- ArgumentList *declAl = md->declArgumentList();
- ArgumentList *defAl = md->argumentList();
+ const ArgumentList *declAl = md->declArgumentList();
+ const ArgumentList *defAl = md->argumentList();
if (declAl && defAl && declAl->count()>0)
{
ArgumentListIterator declAli(*declAl);
ArgumentListIterator defAli(*defAl);
- Argument *a;
+ const Argument *a;
for (declAli.toFirst();(a=declAli.current());++declAli)
{
Argument *defArg = defAli.current();
@@ -908,7 +910,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
else
{
ArgumentListIterator ali(*md->argumentList());
- Argument *a;
+ const Argument *a;
for (ali.toFirst();(a=ali.current());++ali)
{
t << " <param><defname>" << a->type << "</defname></param>" << endl;
@@ -932,11 +934,11 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
if (md->memberType()==MemberType_Enumeration) // enum
{
- MemberList *enumFields = md->enumFieldList();
+ const MemberList *enumFields = md->enumFieldList();
if (enumFields)
{
MemberListIterator emli(*enumFields);
- MemberDef *emd;
+ const MemberDef *emd;
for (emli.toFirst();(emd=emli.current());++emli)
{
ti << " <member refid=\"" << memberOutputFileBase(md)
@@ -1011,7 +1013,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
if (mdict)
{
MemberSDict::Iterator mdi(*mdict);
- MemberDef *rmd;
+ const MemberDef *rmd;
for (mdi.toFirst();(rmd=mdi.current());++mdi)
{
writeMemberReference(t,def,rmd,"references");
@@ -1021,7 +1023,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
if (mdict)
{
MemberSDict::Iterator mdi(*mdict);
- MemberDef *rmd;
+ const MemberDef *rmd;
for (mdi.toFirst();(rmd=mdi.current());++mdi)
{
writeMemberReference(t,def,rmd,"referencedby");
@@ -1033,20 +1035,20 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De
// namespace members are also inserted in the file scope, but
// to prevent this duplication in the XML output, we optionally filter those here.
-static bool memberVisible(Definition *d,MemberDef *md)
+static bool memberVisible(const Definition *d,const MemberDef *md)
{
return Config_getBool(XML_NS_MEMB_FILE_SCOPE) ||
d->definitionType()!=Definition::TypeFile ||
md->getNamespaceDef()==0;
}
-static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t,
+static void generateXMLSection(const Definition *d,FTextStream &ti,FTextStream &t,
MemberList *ml,const char *kind,const char *header=0,
const char *documentation=0)
{
if (ml==0) return;
MemberListIterator mli(*ml);
- MemberDef *md;
+ const MemberDef *md;
int count=0;
for (mli.toFirst();(md=mli.current());++mli)
{
@@ -1079,7 +1081,7 @@ static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t,
t << " </sectiondef>" << endl;
}
-static void writeListOfAllMembers(ClassDef *cd,FTextStream &t)
+static void writeListOfAllMembers(const ClassDef *cd,FTextStream &t)
{
t << " <listofallmembers>" << endl;
if (cd->memberNameInfoSDict())
@@ -1092,7 +1094,7 @@ static void writeListOfAllMembers(ClassDef *cd,FTextStream &t)
MemberInfo *mi;
for (mii.toFirst();(mi=mii.current());++mii)
{
- MemberDef *md=mi->memberDef;
+ const MemberDef *md=mi->memberDef;
if (md->name().at(0)!='@') // skip anonymous members
{
Protection prot = mi->prot;
@@ -1132,7 +1134,7 @@ static void writeInnerClasses(const ClassSDict *cl,FTextStream &t)
if (cl)
{
ClassSDict::Iterator cli(*cl);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes
@@ -1157,7 +1159,7 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
if (nl)
{
NamespaceSDict::Iterator nli(*nl);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes
@@ -1206,7 +1208,7 @@ static void writeInnerGroups(const GroupList *gl,FTextStream &t)
if (gl)
{
GroupListIterator gli(*gl);
- GroupDef *sgd;
+ const GroupDef *sgd;
for (gli.toFirst();(sgd=gli.current());++gli)
{
t << " <innergroup refid=\"" << sgd->getOutputFileBase()
@@ -1230,7 +1232,7 @@ static void writeInnerDirs(const DirList *dl,FTextStream &t)
}
}
-static void generateXMLForClass(ClassDef *cd,FTextStream &ti)
+static void generateXMLForClass(const ClassDef *cd,FTextStream &ti)
{
// + brief description
// + detailed description
@@ -1407,14 +1409,14 @@ static void generateXMLForClass(ClassDef *cd,FTextStream &ti)
t << " <detaileddescription>" << endl;
writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
t << " </detaileddescription>" << endl;
- DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
+ DotClassGraph inheritanceGraph(cd,Inheritance);
if (!inheritanceGraph.isTrivial())
{
t << " <inheritancegraph>" << endl;
inheritanceGraph.writeXML(t);
t << " </inheritancegraph>" << endl;
}
- DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
+ DotClassGraph collaborationGraph(cd,Collaboration);
if (!collaborationGraph.isTrivial())
{
t << " <collaborationgraph>" << endl;
@@ -1443,7 +1445,7 @@ static void generateXMLForClass(ClassDef *cd,FTextStream &ti)
ti << " </compound>" << endl;
}
-static void generateXMLForNamespace(NamespaceDef *nd,FTextStream &ti)
+static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti)
{
// + contained class definitions
// + contained namespace definitions
@@ -1659,7 +1661,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti)
ti << " </compound>" << endl;
}
-static void generateXMLForGroup(GroupDef *gd,FTextStream &ti)
+static void generateXMLForGroup(const GroupDef *gd,FTextStream &ti)
{
// + members
// + member groups
@@ -1983,7 +1985,7 @@ void generateXML()
{
ClassSDict::Iterator cli(*Doxygen::classSDict);
- ClassDef *cd;
+ const ClassDef *cd;
for (cli.toFirst();(cd=cli.current());++cli)
{
generateXMLForClass(cd,t);
@@ -1999,7 +2001,7 @@ void generateXML()
// }
//}
NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
- NamespaceDef *nd;
+ const NamespaceDef *nd;
for (nli.toFirst();(nd=nli.current());++nli)
{
msg("Generating XML output for namespace %s\n",nd->name().data());
@@ -2018,7 +2020,7 @@ void generateXML()
}
}
GroupSDict::Iterator gli(*Doxygen::groupSDict);
- GroupDef *gd;
+ const GroupDef *gd;
for (;(gd=gli.current());++gli)
{
msg("Generating XML output for group %s\n",gd->name().data());
diff --git a/src/xmlgen.h b/src/xmlgen.h
index 0555546..4458b9f 100644
--- a/src/xmlgen.h
+++ b/src/xmlgen.h
@@ -39,7 +39,7 @@ class XMLCodeGenerator : public CodeOutputInterface
void writeCodeAnchor(const char *);
void writeLineNumber(const char *extRef,const char *compId,
const char *anchorId,int l);
- void setCurrentDoc(Definition *,const char *,bool){}
+ void setCurrentDoc(const Definition *,const char *,bool){}
void addWord(const char *,bool){}
void finish();
diff --git a/src/xmlscanner.h b/src/xmlscanner.h
index 6053b96..cb9792c 100644
--- a/src/xmlscanner.h
+++ b/src/xmlscanner.h
@@ -41,9 +41,9 @@ public:
int startLine=-1,
int endLine=-1,
bool inlineFragment=FALSE,
- MemberDef *memberDef=0,
+ const MemberDef *memberDef=0,
bool showLineNumbers=TRUE,
- Definition *searchCtx=0,
+ const Definition *searchCtx=0,
bool collectXRefs=TRUE
)
{
diff --git a/templates/html/jquery.js b/templates/html/jquery.js
index 64861eb..103c32d 100644
--- a/templates/html/jquery.js
+++ b/templates/html/jquery.js
@@ -1,5 +1,5 @@
-/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
-!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:n.sort,splice:n.splice},w.extend=w.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||g(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)n=a[t],a!==(r=e[t])&&(l&&r&&(w.isPlainObject(r)||(i=Array.isArray(r)))?(i?(i=!1,o=n&&Array.isArray(n)?n:[]):o=n&&w.isPlainObject(n)?n:{},a[t]=w.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},w.extend({expando:"jQuery"+("3.3.1"+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==c.call(e))&&(!(t=i(e))||"function"==typeof(n=f.call(t,"constructor")&&t.constructor)&&p.call(n)===d)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e){m(e)},each:function(e,t){var n,r=0;if(C(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(C(Object(e))?w.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:u.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r,i=[],o=0,a=e.length,s=!n;o<a;o++)(r=!t(e[o],o))!==s&&i.push(e[o]);return i},map:function(e,t,n){var r,i,o=0,s=[];if(C(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&s.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&s.push(i);return a.apply([],s)},guid:1,support:h}),"function"==typeof Symbol&&(w.fn[Symbol.iterator]=n[Symbol.iterator]),w.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function C(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!g(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},P="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",I="\\["+M+"*("+R+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+R+"))|)"+M+"*\\]",W=":("+R+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+I+")*)|.*)\\)|)",$=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),F=new RegExp("^"+M+"*,"+M+"*"),_=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="<a id='"+b+"'></a><select id='"+b+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:he(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:he(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=r.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})r.pseudos[t]=fe(t);for(t in{submit:!0,reset:!0})r.pseudos[t]=pe(t);function ye(){}ye.prototype=r.filters=r.pseudos,r.setFilters=new ye,a=oe.tokenize=function(e,t){var n,i,o,a,s,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=r.preFilter;while(s){n&&!(i=F.exec(s))||(i&&(s=s.slice(i[0].length)||s),u.push(o=[])),n=!1,(i=_.exec(s))&&(n=i.shift(),o.push({value:n,type:i[0].replace(B," ")}),s=s.slice(n.length));for(a in r.filter)!(i=V[a].exec(s))||l[a]&&!(i=l[a](i))||(n=i.shift(),o.push({value:n,type:a,matches:i}),s=s.slice(n.length));if(!n)break}return t?s.length:s?oe.error(e):k(e,u).slice(0)};function ve(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function me(e,t,n){var r=t.dir,i=t.next,o=i||r,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||a)return e(t,n,i);return!1}:function(t,n,u){var l,c,f,p=[T,s];if(u){while(t=t[r])if((1===t.nodeType||a)&&e(t,n,u))return!0}else while(t=t[r])if(1===t.nodeType||a)if(f=t[b]||(t[b]={}),c=f[t.uniqueID]||(f[t.uniqueID]={}),i&&i===t.nodeName.toLowerCase())t=t[r]||t;else{if((l=c[o])&&l[0]===T&&l[1]===s)return p[2]=l[2];if(c[o]=p,p[2]=e(t,n,u))return!0}return!1}}function xe(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r<i;r++)oe(e,t[r],n);return n}function we(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Te(e,t,n,r,i,o){return r&&!r[b]&&(r=Te(r)),i&&!i[b]&&(i=Te(i,o)),se(function(o,a,s,u){var l,c,f,p=[],d=[],h=a.length,g=o||be(t||"*",s.nodeType?[s]:s,[]),y=!e||!o&&t?g:we(g,p,e,s,u),v=n?i||(o?e:h||r)?[]:a:y;if(n&&n(y,v,s,u),r){l=we(v,d),r(l,[],s,u),c=l.length;while(c--)(f=l[c])&&(v[d[c]]=!(y[d[c]]=f))}if(o){if(i||e){if(i){l=[],c=v.length;while(c--)(f=v[c])&&l.push(y[c]=f);i(null,v=[],l,u)}c=v.length;while(c--)(f=v[c])&&(l=i?O(o,f):p[c])>-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u<o;u++)if(n=r.relative[e[u].type])p=[me(xe(p),n)];else{if((n=r.filter[e[u].type].apply(null,e[u].matches))[b]){for(i=++u;i<o;i++)if(r.relative[e[i].type])break;return Te(u>1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u<i&&Ce(e.slice(u,i)),i<o&&Ce(e=e.slice(i)),i<o&&ve(e))}p.push(n)}return xe(p)}function Ee(e,t){var n=t.length>0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t<r;t++)if(w.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)w.find(e,i[t],n);return r>1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(w.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&w(e);if(!D.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?a.index(n)>-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s<o.length)!1===o[s].apply(n[0],n[1])&&e.stopOnFalse&&(s=o.length,n=!1)}e.memory||(n=!1),t=!1,i&&(o=n?[]:"")},l={add:function(){return o&&(n&&!t&&(s=o.length-1,a.push(n)),function t(n){w.each(n,function(n,r){g(r)?e.unique&&l.has(r)||o.push(r):r&&r.length&&"string"!==x(r)&&t(r)})}(arguments),n&&!t&&u()),this},remove:function(){return w.each(arguments,function(e,t){var n;while((n=w.inArray(t,o,n))>-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t<o)){if((e=r.apply(s,u))===n.promise())throw new TypeError("Thenable self-resolution");l=e&&("object"==typeof e||"function"==typeof e)&&e.then,g(l)?i?l.call(e,a(o,n,I,i),a(o,n,W,i)):(o++,l.call(e,a(o,n,I,i),a(o,n,W,i),a(o,n,I,n.notifyWith))):(r!==I&&(s=void 0,u=[e]),(i||n.resolveWith)(s,u))}},c=i?l:function(){try{l()}catch(e){w.Deferred.exceptionHook&&w.Deferred.exceptionHook(e,c.stackTrace),t+1>=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},X=/^-ms-/,U=/-([a-z])/g;function V(e,t){return t.toUpperCase()}function G(e){return e.replace(X,"ms-").replace(U,V)}var Y=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Q(){this.expando=w.expando+Q.uid++}Q.uid=1,Q.prototype={cache:function(e){var t=e[this.expando];return t||(t={},Y(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[G(t)]=n;else for(r in t)i[G(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][G(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(G):(t=G(t))in r?[t]:t.match(M)||[]).length;while(n--)delete r[t[n]]}(void 0===t||w.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!w.isEmptyObject(t)}};var J=new Q,K=new Q,Z=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,ee=/[A-Z]/g;function te(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Z.test(e)?JSON.parse(e):e)}function ne(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(ee,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=te(n)}catch(e){}K.set(e,t,n)}else n=void 0;return n}w.extend({hasData:function(e){return K.hasData(e)||J.hasData(e)},data:function(e,t,n){return K.access(e,t,n)},removeData:function(e,t){K.remove(e,t)},_data:function(e,t,n){return J.access(e,t,n)},_removeData:function(e,t){J.remove(e,t)}}),w.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=K.get(o),1===o.nodeType&&!J.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&(r=G(r.slice(5)),ne(o,r,i[r]));J.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){K.set(this,e)}):z(this,function(t){var n;if(o&&void 0===t){if(void 0!==(n=K.get(o,e)))return n;if(void 0!==(n=ne(o,e)))return n}else this.each(function(){K.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length<n?w.queue(this[0],e):void 0===t?this:this.each(function(){var n=w.queue(this,e,t);w._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&w.dequeue(this,e)})},dequeue:function(e){return this.each(function(){w.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=w.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=J.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var re=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ie=new RegExp("^(?:([+-])=|)("+re+")([a-z%]*)$","i"),oe=["Top","Right","Bottom","Left"],ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&w.contains(e.ownerDocument,e)&&"none"===w.css(e,"display")},se=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i};function ue(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return w.css(e,t,"")},u=s(),l=n&&n[3]||(w.cssNumber[t]?"":"px"),c=(w.cssNumber[t]||"px"!==l&&+u)&&ie.exec(w.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)w.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,w.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var le={};function ce(e){var t,n=e.ownerDocument,r=e.nodeName,i=le[r];return i||(t=n.body.appendChild(n.createElement(r)),i=w.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),le[r]=i,i)}function fe(e,t){for(var n,r,i=[],o=0,a=e.length;o<a;o++)(r=e[o]).style&&(n=r.style.display,t?("none"===n&&(i[o]=J.get(r,"display")||null,i[o]||(r.style.display="")),""===r.style.display&&ae(r)&&(i[o]=ce(r))):"none"!==n&&(i[o]="none",J.set(r,"display",n)));for(o=0;o<a;o++)null!=i[o]&&(e[o].style.display=i[o]);return e}w.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?w(this).show():w(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n<r;n++)J.set(e[n],"globalEval",!t||J.get(t[n],"globalEval"))}var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))w.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+w.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;w.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&w.inArray(o,r)>-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="<textarea>x</textarea>",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n<arguments.length;n++)u[n]=arguments[n];if(t.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,t)){s=w.event.handlers.call(this,t,l),n=0;while((o=s[n++])&&!t.isPropagationStopped()){t.currentTarget=o.elem,r=0;while((a=o.handlers[r++])&&!t.isImmediatePropagationStopped())t.rnamespace&&!t.rnamespace.test(a.namespace)||(t.handleObj=a,t.data=a.data,void 0!==(i=((w.event.special[a.origType]||{}).handle||a.handler).apply(o.elem,u))&&!1===(t.result=i)&&(t.preventDefault(),t.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,t),t.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&e.button>=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?w(i,this).index(l)>-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(e,t){Object.defineProperty(w.Event.prototype,e,{enumerable:!0,configurable:!0,get:g(t)?function(){if(this.originalEvent)return t(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[e]},set:function(t){Object.defineProperty(this,e,{enumerable:!0,configurable:!0,writable:!0,value:t})}})},fix:function(e){return e[w.expando]?e:new w.Event(e)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==Se()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===Se()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&N(this,"input"))return this.click(),!1},_default:function(e){return N(e.target,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},w.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},w.Event=function(e,t){if(!(this instanceof w.Event))return new w.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ee:ke,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&w.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[w.expando]=!0},w.Event.prototype={constructor:w.Event,isDefaultPrevented:ke,isPropagationStopped:ke,isImmediatePropagationStopped:ke,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ee,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ee,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ee,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},w.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&we.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Te.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},w.event.addProp),w.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,t){w.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return i&&(i===r||w.contains(r,i))||(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),w.fn.extend({on:function(e,t,n,r){return De(this,e,t,n,r)},one:function(e,t,n,r){return De(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,w(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=ke),this.each(function(){w.event.remove(this,e,n,t)})}});var Ne=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/<script|<style|<link/i,je=/checked\s*(?:[^=]|=\s*.checked.)/i,qe=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n<r;n++)w.event.add(t,i,l[i][n])}K.hasData(e)&&(s=K.access(e),u=w.extend({},s),K.set(t,u))}}function Me(e,t){var n=t.nodeName.toLowerCase();"input"===n&&pe.test(e.type)?t.checked=e.checked:"input"!==n&&"textarea"!==n||(t.defaultValue=e.defaultValue)}function Re(e,t,n,r){t=a.apply([],t);var i,o,s,u,l,c,f=0,p=e.length,d=p-1,y=t[0],v=g(y);if(v||p>1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f<p;f++)l=i,f!==d&&(l=w.clone(l,!0,!0),u&&w.merge(s,ye(l,"script"))),n.call(e[f],l,f);if(u)for(c=s[s.length-1].ownerDocument,w.map(s,Oe),f=0;f<u;f++)l=s[f],he.test(l.type||"")&&!J.access(l,"globalEval")&&w.contains(c,l)&&(l.src&&"module"!==(l.type||"").toLowerCase()?w._evalUrl&&w._evalUrl(l.src):m(l.textContent.replace(qe,""),c,l))}return e}function Ie(e,t,n){for(var r,i=t?w.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||w.cleanData(ye(r)),r.parentNode&&(n&&w.contains(r.ownerDocument,r)&&ve(ye(r,"script")),r.parentNode.removeChild(r));return e}w.extend({htmlPrefilter:function(e){return e.replace(Ne,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r<i;r++)Me(o[r],a[r]);if(t)if(n)for(o=o||ye(e),a=a||ye(s),r=0,i=o.length;r<i;r++)Pe(o[r],a[r]);else Pe(e,s);return(a=ye(s,"script")).length>0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(w.cleanData(ye(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=[];return Re(this,arguments,function(t){var n=this.parentNode;w.inArray(this,e)<0&&(w.cleanData(ye(this)),n&&n.replaceChild(t,this))},e)}}),w.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){w.fn[e]=function(e){for(var n,r=[],i=w(e),o=i.length-1,a=0;a<=o;a++)n=a===o?this:this.clone(!0),w(i[a])[t](n),s.apply(r,n.get());return this.pushStack(r)}});var We=new RegExp("^("+re+")(?!px)[a-z%]+$","i"),$e=function(t){var n=t.ownerDocument.defaultView;return n&&n.opener||(n=e),n.getComputedStyle(t)},Be=new RegExp(oe.join("|"),"i");!function(){function t(){if(c){l.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",c.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",be.appendChild(l).appendChild(c);var t=e.getComputedStyle(c);i="1%"!==t.top,u=12===n(t.marginLeft),c.style.right="60%",s=36===n(t.right),o=36===n(t.width),c.style.position="absolute",a=36===c.offsetWidth||"absolute",be.removeChild(l),c=null}}function n(e){return Math.round(parseFloat(e))}var i,o,a,s,u,l=r.createElement("div"),c=r.createElement("div");c.style&&(c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",h.clearCloneStyle="content-box"===c.style.backgroundClip,w.extend(h,{boxSizingReliable:function(){return t(),o},pixelBoxStyles:function(){return t(),s},pixelPosition:function(){return t(),i},reliableMarginLeft:function(){return t(),u},scrollboxSize:function(){return t(),a}}))}();function Fe(e,t,n){var r,i,o,a,s=e.style;return(n=n||$e(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||w.contains(e.ownerDocument,e)||(a=w.style(e,t)),!h.pixelBoxStyles()&&We.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function _e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}var ze=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ue={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","Moz","ms"],Ye=r.createElement("div").style;function Qe(e){if(e in Ye)return e;var t=e[0].toUpperCase()+e.slice(1),n=Ge.length;while(n--)if((e=Ge[n]+t)in Ye)return e}function Je(e){var t=w.cssProps[e];return t||(t=w.cssProps[e]=Qe(e)||e),t}function Ke(e,t,n){var r=ie.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ze(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=w.css(e,n+oe[a],!0,i)),r?("content"===n&&(u-=w.css(e,"padding"+oe[a],!0,i)),"margin"!==n&&(u-=w.css(e,"border"+oe[a]+"Width",!0,i))):(u+=w.css(e,"padding"+oe[a],!0,i),"padding"!==n?u+=w.css(e,"border"+oe[a]+"Width",!0,i):s+=w.css(e,"border"+oe[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a<i;a++)o[t[a]]=w.css(e,t[a],!1,r);return o}return void 0!==n?w.style(e,t,n):w.css(e,t)},e,t,arguments.length>1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ct(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),y=J.get(e,"fxshow");n.queue||(null==(a=w._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,w.queue(e,"fx").length||a.empty.fire()})}));for(r in t)if(i=t[r],it.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!y||void 0===y[r])continue;g=!0}d[r]=y&&y[r]||w.style(e,r)}if((u=!w.isEmptyObject(t))||!w.isEmptyObject(d)){f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=y&&y.display)&&(l=J.get(e,"display")),"none"===(c=w.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=w.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===w.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1;for(r in d)u||(y?"hidden"in y&&(g=y.hidden):y=J.access(e,"fxshow",{display:l}),o&&(y.hidden=!g),g&&fe([e],!0),p.done(function(){g||fe([e]),J.remove(e,"fxshow");for(r in d)w.style(e,r,d[r])})),u=lt(g?y[r]:0,r,p),r in y||(y[r]=u.start,g&&(u.end=u.start,u.start=0))}}function ft(e,t){var n,r,i,o,a;for(n in e)if(r=G(n),i=t[r],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=w.cssHooks[r])&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}function pt(e,t,n){var r,i,o=0,a=pt.prefilters.length,s=w.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;for(var t=nt||st(),n=Math.max(0,l.startTime+l.duration-t),r=1-(n/l.duration||0),o=0,a=l.tweens.length;o<a;o++)l.tweens[o].run(r);return s.notifyWith(e,[l,r,n]),r<1&&a?n:(a||s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:w.extend({},t),opts:w.extend(!0,{specialEasing:{},easing:w.easing._default},n),originalProperties:t,originalOptions:n,startTime:nt||st(),duration:n.duration,tweens:[],createTween:function(t,n){var r=w.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;n<r;n++)l.tweens[n].run(1);return t?(s.notifyWith(e,[l,1,0]),s.resolveWith(e,[l,t])):s.rejectWith(e,[l,t]),this}}),c=l.props;for(ft(c,l.opts.specialEasing);o<a;o++)if(r=pt.prefilters[o].call(l,e,c,l.opts))return g(r.stop)&&(w._queueHooks(l.elem,l.opts.queue).stop=r.stop.bind(r)),r;return w.map(c,lt,l),g(l.opts.start)&&l.opts.start.call(e,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),w.fx.timer(w.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l}w.Animation=w.extend(pt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return ue(n.elem,e,ie.exec(t),n),n}]},tweener:function(e,t){g(e)?(t=e,e=["*"]):e=e.match(M);for(var n,r=0,i=e.length;r<i;r++)n=e[r],pt.tweeners[n]=pt.tweeners[n]||[],pt.tweeners[n].unshift(t)},prefilters:[ct],prefilter:function(e,t){t?pt.prefilters.unshift(e):pt.prefilters.push(e)}}),w.speed=function(e,t,n){var r=e&&"object"==typeof e?w.extend({},e):{complete:n||!n&&t||g(e)&&e,duration:e,easing:n&&t||t&&!g(t)&&t};return w.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in w.fx.speeds?r.duration=w.fx.speeds[r.duration]:r.duration=w.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){g(r.old)&&r.old.call(this),r.queue&&w.dequeue(this,r.queue)},r},w.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=w.isEmptyObject(e),o=w.speed(t,n,r),a=function(){var t=pt(this,w.extend({},e),o);(i||J.get(this,"finish"))&&t.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=void 0),t&&!1!==e&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=w.timers,a=J.get(this);if(i)a[i]&&a[i].stop&&r(a[i]);else for(i in a)a[i]&&a[i].stop&&ot.test(i)&&r(a[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));!t&&n||w.dequeue(this,e)})},finish:function(e){return!1!==e&&(e=e||"fx"),this.each(function(){var t,n=J.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=w.timers,a=r?r.length:0;for(n.finish=!0,w.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;t<a;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}}),w.each(["toggle","show","hide"],function(e,t){var n=w.fn[t];w.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ut(t,!0),e,r,i)}}),w.each({slideDown:ut("show"),slideUp:ut("hide"),slideToggle:ut("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){w.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),w.timers=[],w.fx.tick=function(){var e,t=0,n=w.timers;for(nt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||w.fx.stop(),nt=void 0},w.fx.timer=function(e){w.timers.push(e),w.fx.start()},w.fx.interval=13,w.fx.start=function(){rt||(rt=!0,at())},w.fx.stop=function(){rt=null},w.fx.speeds={slow:600,fast:200,_default:400},w.fn.delay=function(t,n){return t=w.fx?w.fx.speeds[t]||t:t,n=n||"fx",this.queue(n,function(n,r){var i=e.setTimeout(n,t);r.stop=function(){e.clearTimeout(i)}})},function(){var e=r.createElement("input"),t=r.createElement("select").appendChild(r.createElement("option"));e.type="checkbox",h.checkOn=""!==e.value,h.optSelected=t.selected,(e=r.createElement("input")).value="t",e.type="radio",h.radioValue="t"===e.value}();var dt,ht=w.expr.attrHandle;w.fn.extend({attr:function(e,t){return z(this,w.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!N(n.parentNode,"optgroup"))){if(t=w(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=w.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=w.inArray(w.valHooks.option.get(r),o)>-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("<script>").prop({charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&o("error"===e.type?404:200,e.type)}),r.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Yt=[],Qt=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Yt.pop()||w.expando+"_"+Et++;return this[e]=!0,e}}),w.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,a,s=!1!==t.jsonp&&(Qt.test(t.url)?"url":"string"==typeof t.data&&0===(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&Qt.test(t.data)&&"data");if(s||"jsonp"===t.dataTypes[0])return i=t.jsonpCallback=g(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Qt,"$1"+i):!1!==t.jsonp&&(t.url+=(kt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return a||w.error(i+" was not called"),a[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){a=arguments},r.always(function(){void 0===o?w(e).removeProp(i):e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,Yt.push(i)),a&&g(o)&&o(a[0]),a=o=void 0}),"script"}),h.createHTMLDocument=function(){var e=r.implementation.createHTMLDocument("").body;return e.innerHTML="<form></form><form></form>",2===e.childNodes.length}(),w.parseHTML=function(e,t,n){if("string"!=typeof e)return[];"boolean"==typeof t&&(n=t,t=!1);var i,o,a;return t||(h.createHTMLDocument?((i=(t=r.implementation.createHTMLDocument("")).createElement("base")).href=r.location.href,t.head.appendChild(i)):t=r),o=A.exec(e),a=!n&&[],o?[t.createElement(o[1])]:(o=xe([e],t,a),a&&a.length&&w(a).remove(),w.merge([],o.childNodes))},w.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return s>-1&&(r=vt(e.slice(s)),e=e.slice(0,s)),g(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),a.length>0&&w.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?w("<div>").append(w.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}}),w.expr.pseudos.animated=function(e){return w.grep(w.timers,function(t){return e===t.elem}).length},w.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l,c=w.css(e,"position"),f=w(e),p={};"static"===c&&(e.style.position="relative"),s=f.offset(),o=w.css(e,"top"),u=w.css(e,"left"),(l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1)?(a=(r=f.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),g(t)&&(t=t.call(e,n,w.extend({},s))),null!=t.top&&(p.top=t.top-s.top+a),null!=t.left&&(p.left=t.left-s.left+i),"using"in t?t.using.call(e,p):f.css(p)}},w.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){w.offset.setOffset(this,e,t)});var t,n,r=this[0];if(r)return r.getClientRects().length?(t=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:t.top+n.pageYOffset,left:t.left+n.pageXOffset}):{top:0,left:0}},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===w.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===w.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=w(e).offset()).top+=w.css(e,"borderTopWidth",!0),i.left+=w.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-w.css(r,"marginTop",!0),left:t.left-i.left-w.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===w.css(e,"position"))e=e.offsetParent;return e||be})}}),w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,t){var n="pageYOffset"===t;w.fn[e]=function(r){return z(this,function(e,r,i){var o;if(y(e)?o=e:9===e.nodeType&&(o=e.defaultView),void 0===i)return o?o[t]:e[r];o?o.scrollTo(n?o.pageXOffset:i,n?i:o.pageYOffset):e[r]=i},e,r,arguments.length)}}),w.each(["top","left"],function(e,t){w.cssHooks[t]=_e(h.pixelPosition,function(e,n){if(n)return n=Fe(e,t),We.test(n)?w(e).position()[t]+"px":n})}),w.each({Height:"height",Width:"width"},function(e,t){w.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){w.fn[r]=function(i,o){var a=arguments.length&&(n||"boolean"!=typeof i),s=n||(!0===i||!0===o?"margin":"border");return z(this,function(t,n,i){var o;return y(t)?0===r.indexOf("outer")?t["inner"+e]:t.document.documentElement["client"+e]:9===t.nodeType?(o=t.documentElement,Math.max(t.body["scroll"+e],o["scroll"+e],t.body["offset"+e],o["offset"+e],o["client"+e])):void 0===i?w.css(t,n,s):w.style(t,n,i,s)},t,a?i:void 0,a)}})}),w.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),w.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),w.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),g(e))return r=o.call(arguments,2),i=function(){return e.apply(t||this,r.concat(o.call(arguments)))},i.guid=e.guid=e.guid||w.guid++,i},w.holdReady=function(e){e?w.readyWait++:w.ready(!0)},w.isArray=Array.isArray,w.parseJSON=JSON.parse,w.nodeName=N,w.isFunction=g,w.isWindow=y,w.camelCase=G,w.type=x,w.now=Date.now,w.isNumeric=function(e){var t=w.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return w});var Jt=e.jQuery,Kt=e.$;return w.noConflict=function(t){return e.$===w&&(e.$=Kt),t&&e.jQuery===w&&(e.jQuery=Jt),w},t||(e.jQuery=e.$=w),w});
+/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
/*! jQuery UI - v1.12.1 - 2019-01-27
* http://jqueryui.com
* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/resizable.js, widgets/mouse.js
@@ -20,7 +20,7 @@
Released under MIT license.
https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
*/
-!function(e,t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(h){var v=h(document),n=h(window),e=h("body"),m="displayController",T="hasActiveHover",g="forcedOpen",i="hasMouseMove",y="mouseOnToPopup",a="originalTitle",b="powertip",H="powertipjq",k="powertiptarget",P=".powertip",O=180/Math.PI,t=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"],I={elements:null,tooltips:null,isTipOpen:!1,isFixedTipOpen:!1,isClosing:!1,tipOpenImminent:!1,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:!1,delayInProgress:!1,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0},l={none:0,top:1,bottom:2,left:4,right:8};function x(){var o=this;o.top="auto",o.left="auto",o.right="auto",o.bottom="auto",o.set=function(e,t){h.isNumeric(t)&&(o[e]=Math.round(t))}}function c(o,n,i){var s=null,t=null;function r(e,t){a(),o.data(T)?l():e?(t&&o.data(g,!0),c(),i.showTip(o)):(I.tipOpenImminent=!0,s=setTimeout(function(){var e,t;s=null,e=Math.abs(I.previousX-I.currentX),t=Math.abs(I.previousY-I.currentY),e+t<n.intentSensitivity?(l(),c(),i.showTip(o)):(I.previousX=I.currentX,I.previousY=I.currentY,r())},n.intentPollInterval))}function a(e){s=clearTimeout(s),(I.closeDelayTimeout&&t===I.closeDelayTimeout||e)&&l()}function l(){I.closeDelayTimeout=clearTimeout(I.closeDelayTimeout),I.delayInProgress=!1}function c(){I.delayInProgress&&I.activeHover&&!I.activeHover.is(o)&&I.activeHover.data(m).hide(!0)}this.show=r,this.hide=function(e){t&&(t=I.closeDelayTimeout=clearTimeout(t),I.delayInProgress=!1),a(),I.tipOpenImminent=!1,o.data(T)&&(o.data(g,!1),e?i.hideTip(o):(I.delayInProgress=!0,I.closeDelayTimeout=setTimeout(function(){I.closeDelayTimeout=null,i.hideTip(o),I.delayInProgress=!1,t=null},n.closeDelay),t=I.closeDelayTimeout))},this.cancel=a,this.resetPosition=function(){i.resetPosition(o)}}function o(){this.compute=function(e,t,o,n,i){var s,r,a=t.split("-")[0],l=new x;switch(r=e,s=Boolean(window.SVGElement&&r[0]instanceof SVGElement)?function(e,t){var o,n,i,s,r=e.closest("svg")[0],a=e[0],l=r.createSVGPoint(),c=a.getBBox(),u=a.getScreenCTM(),p=c.width/2,f=c.height/2,w=[],d=["nw","n","ne","e","se","s","sw","w"];function h(){w.push(l.matrixTransform(u))}if(l.x=c.x,l.y=c.y,h(),l.x+=p,h(),l.x+=p,h(),l.y+=f,h(),l.y+=f,h(),l.x-=p,h(),l.x-=p,h(),l.y-=f,h(),w[0].y!==w[1].y||w[0].x!==w[7].x)for(n=Math.atan2(u.b,u.a)*O,(i=Math.ceil((n%360-22.5)/45))<1&&(i+=8);i--;)d.push(d.shift());for(s=0;s<w.length;s++)if(d[s]===t){o=w[s];break}return{top:o.y+I.scrollTop,left:o.x+I.scrollLeft}}(e,a):function(e,t){var o,n,i=e.offset(),s=e.outerWidth(),r=e.outerHeight();switch(t){case"n":o=i.left+s/2,n=i.top;break;case"e":o=i.left+s,n=i.top+r/2;break;case"s":o=i.left+s/2,n=i.top+r;break;case"w":o=i.left,n=i.top+r/2;break;case"nw":o=i.left,n=i.top;break;case"ne":o=i.left+s,n=i.top;break;case"sw":o=i.left,n=i.top+r;break;case"se":o=i.left+s,n=i.top+r}return{top:n,left:o}}(e,a),t){case"n":l.set("left",s.left-o/2),l.set("bottom",I.windowHeight-s.top+i);break;case"e":l.set("left",s.left+i),l.set("top",s.top-n/2);break;case"s":l.set("left",s.left-o/2),l.set("top",s.top+i);break;case"w":l.set("top",s.top-n/2),l.set("right",I.windowWidth-s.left+i);break;case"nw":l.set("bottom",I.windowHeight-s.top+i),l.set("right",I.windowWidth-s.left-20);break;case"nw-alt":l.set("left",s.left),l.set("bottom",I.windowHeight-s.top+i);break;case"ne":l.set("left",s.left-20),l.set("bottom",I.windowHeight-s.top+i);break;case"ne-alt":l.set("bottom",I.windowHeight-s.top+i),l.set("right",I.windowWidth-s.left);break;case"sw":l.set("top",s.top+i),l.set("right",I.windowWidth-s.left-20);break;case"sw-alt":l.set("left",s.left),l.set("top",s.top+i);break;case"se":l.set("left",s.left-20),l.set("top",s.top+i);break;case"se-alt":l.set("top",s.top+i),l.set("right",I.windowWidth-s.left)}return l}}function u(c){var r=new o,u=h("#"+c.popupId);function p(t){I.isClosing=!0,I.isTipOpen=!1,I.desyncTimeout=clearInterval(I.desyncTimeout),t.data(T,!1),t.data(g,!1),v.off("click"+P),u.off(P),u.fadeOut(c.fadeOutTime,function(){var e=new x;I.activeHover=null,I.isClosing=!1,I.isFixedTipOpen=!1,u.removeClass(),e.set("top",I.currentY+c.offset),e.set("left",I.currentX+c.offset),u.css(e),t.trigger("powerTipClose")})}function f(){var e,t,o,n;!I.isFixedTipOpen&&(I.isTipOpen||I.tipOpenImminent&&u.data(i))&&(e=u.outerWidth(),t=u.outerHeight(),(o=new x).set("top",I.currentY+c.offset),o.set("left",I.currentX+c.offset),(n=M(o,e,t))!==l.none&&(1===function(e){var t=0;for(;e;)e&=e-1,t++;return t}(n)?n===l.right?o.set("left",I.scrollLeft+I.windowWidth-e):n===l.bottom&&o.set("top",I.scrollTop+I.windowHeight-t):(o.set("left",I.currentX-e-c.offset),o.set("top",I.currentY-t-c.offset))),u.css(o))}function w(n){var e,i;c.smartPlacement||c.followMouse&&n.data(g)?(e=h.fn.powerTip.smartPlacementLists[c.placement],h.each(e,function(e,t){var o=M(s(n,t),u.outerWidth(),u.outerHeight());return i=t,o!==l.none})):(s(n,c.placement),i=c.placement),u.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt"),u.addClass(i)}function s(e,t){var o,n,i=0,s=new x;for(s.set("top",0),s.set("left",0),u.css(s);o=u.outerWidth(),n=u.outerHeight(),s=r.compute(e,t,o,n,c.offset),u.css(s),++i<=5&&(o!==u.outerWidth()||n!==u.outerHeight()););return s}function d(){var e=!1,t=0<h.grep(["mouseleave","mouseout","blur","focusout"],function(e){return-1!==h.inArray(e,c.closeEvents)}).length;I.isTipOpen&&!I.isClosing&&!I.delayInProgress&&t&&(!1===I.activeHover.data(T)||I.activeHover.is(":disabled")?e=!0:X(I.activeHover)||I.activeHover.is(":focus")||I.activeHover.data(g)||u.data(y)&&X(u)||(e=!0),e&&p(I.activeHover))}0===u.length&&(u=h("<div/>",{id:c.popupId}),0===e.length&&(e=h("body")),e.append(u),I.tooltips=I.tooltips?I.tooltips.add(u):u),c.followMouse&&(u.data(i)||(v.on("mousemove"+P,f),n.on("scroll"+P,f),u.data(i,!0))),this.showTip=function(o){o.data(T,!0),u.queue(function(e){!function t(o){var e;if(o.data(T)){if(I.isTipOpen)return I.isClosing||p(I.activeHover),void u.delay(100).queue(function(e){t(o),e()});var n,i,s,r,a,l;o.trigger("powerTipPreRender"),r=(n=o).data(b),a=n.data(H),l=n.data(k),r?(h.isFunction(r)&&(r=r.call(n[0])),s=r):a?(h.isFunction(a)&&(a=a.call(n[0])),0<a.length&&(s=a.clone(!0,!0))):l&&0<(i=h("#"+l)).length&&(s=i.html()),(e=s)&&(u.empty().append(e),o.trigger("powerTipRender"),I.activeHover=o,I.isTipOpen=!0,u.data(y,c.mouseOnToPopup),u.addClass(c.popupClass),!c.followMouse||o.data(g)?(w(o),I.isFixedTipOpen=!0):f(),o.data(g)||c.followMouse||v.on("click"+P,function(e){var t=e.target;t!==o[0]&&(c.mouseOnToPopup&&(t===u[0]||h.contains(u[0],t))||h.powerTip.hide())}),c.mouseOnToPopup&&!c.manual&&(u.on("mouseenter"+P,function(){I.activeHover&&I.activeHover.data(m).cancel()}),u.on("mouseleave"+P,function(){I.activeHover&&I.activeHover.data(m).hide()})),u.fadeIn(c.fadeInTime,function(){I.desyncTimeout||(I.desyncTimeout=setInterval(d,500)),o.trigger("powerTipOpen")}))}}(o),e()})},this.hideTip=p,this.resetPosition=w}function p(e){return Boolean(e&&-1<h.inArray(e.type,t)&&"number"==typeof e.pageX)}function f(){I.scrollLeft=n.scrollLeft(),I.scrollTop=n.scrollTop(),I.windowWidth=n.width(),I.windowHeight=n.height()}function w(){I.windowWidth=n.width(),I.windowHeight=n.height()}function d(){var e=n.scrollLeft(),t=n.scrollTop();e!==I.scrollLeft&&(I.currentX+=e-I.scrollLeft,I.scrollLeft=e),t!==I.scrollTop&&(I.currentY+=t-I.scrollTop,I.scrollTop=t)}function C(e){I.currentX=e.pageX,I.currentY=e.pageY}function X(e){var t=e.offset(),o=e[0].getBoundingClientRect(),n=o.right-o.left,i=o.bottom-o.top;return I.currentX>=t.left&&I.currentX<=t.left+n&&I.currentY>=t.top&&I.currentY<=t.top+i}function M(e,t,o){var n=I.scrollTop,i=I.scrollLeft,s=n+I.windowHeight,r=i+I.windowWidth,a=l.none;return(e.top<n||Math.abs(e.bottom-I.windowHeight)-o<n)&&(a|=l.top),(e.top+o>s||Math.abs(e.bottom-I.windowHeight)>s)&&(a|=l.bottom),(e.left<i||e.right+t>r)&&(a|=l.left),(e.left+t>r||e.right<i)&&(a|=l.right),a}return h.fn.powerTip=function(e,t){var s,r,o=this;return o.length?"string"===h.type(e)&&h.powerTip[e]?h.powerTip[e].call(o,o,t):(s=h.extend({},h.fn.powerTip.defaults,e),h.powerTip.destroy(o),r=new u(s),I.mouseTrackingActive||(I.mouseTrackingActive=!0,f(),h(f),v.on("mousemove"+P,C),n.on("resize"+P,w),n.on("scroll"+P,d)),o.each(function(){var e=h(this),t=e.data(b),o=e.data(H),n=e.data(k),i=e.attr("title");t||n||o||!i||(e.data(b,i),e.data(a,i),e.removeAttr("title")),e.data(m,new c(e,s,r))}),s.manual||(h.each(s.openEvents,function(e,t){-1<h.inArray(t,s.closeEvents)?o.on(t+P,function(e){h.powerTip.toggle(this,e)}):o.on(t+P,function(e){h.powerTip.show(this,e)})}),h.each(s.closeEvents,function(e,t){h.inArray(t,s.openEvents)<0&&o.on(t+P,function(e){h.powerTip.hide(this,!p(e))})}),o.on("keydown"+P,function(e){27===e.keyCode&&h.powerTip.hide(this,!0)})),I.elements=I.elements?I.elements.add(o):o,o):o},h.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:!1,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:!1,offset:10,mouseOnToPopup:!1,manual:!1,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]},h.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]},h.powerTip={show:function(e,t){return p(t)?(C(t),I.previousX=t.pageX,I.previousY=t.pageY,h(e).data(m).show()):h(e).first().data(m).show(!0,!0),e},reposition:function(e){return h(e).first().data(m).resetPosition(),e},hide:function(e,t){var o;return t=!e||t,e?o=h(e).first().data(m):I.activeHover&&(o=I.activeHover.data(m)),o&&o.hide(t),e},toggle:function(e,t){return I.activeHover&&I.activeHover.is(e)?h.powerTip.hide(e,!p(t)):h.powerTip.show(e,t),e},destroy:function(e){var t=e?h(e):I.elements;return I.elements&&0!==I.elements.length&&(I.isTipOpen&&!I.isClosing&&0<t.filter(I.activeHover).length&&(I.delayInProgress&&I.activeHover.data(m).cancel(),h.powerTip.hide(I.activeHover,!0)),t.off(P).each(function(){var e=h(this),t=[a,m,T,g];e.data(a)&&(e.attr("title",e.data(a)),t.push(b)),e.removeData(t)}),I.elements=I.elements.not(t),0===I.elements.length&&(n.off(P),v.off(P),I.mouseTrackingActive=!1,I.tooltips.remove(),I.tooltips=null)),e}},h.powerTip.showTip=h.powerTip.show,h.powerTip.closeTip=h.powerTip.hide,h.powerTip});/*!
+(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory(require("jquery"))}else{factory(root.jQuery)}})(this,function($){var $document=$(document),$window=$(window),$body=$("body");var DATA_DISPLAYCONTROLLER="displayController",DATA_HASACTIVEHOVER="hasActiveHover",DATA_FORCEDOPEN="forcedOpen",DATA_HASMOUSEMOVE="hasMouseMove",DATA_MOUSEONTOTIP="mouseOnToPopup",DATA_ORIGINALTITLE="originalTitle",DATA_POWERTIP="powertip",DATA_POWERTIPJQ="powertipjq",DATA_POWERTIPTARGET="powertiptarget",EVENT_NAMESPACE=".powertip",RAD2DEG=180/Math.PI,MOUSE_EVENTS=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"];var session={tooltips:null,isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var Collision={none:0,top:1,bottom:2,left:4,right:8};$.fn.powerTip=function(opts,arg){var targetElements=this,options,tipController;if(!targetElements.length){return targetElements}if($.type(opts)==="string"&&$.powerTip[opts]){return $.powerTip[opts].call(targetElements,targetElements,arg)}options=$.extend({},$.fn.powerTip.defaults,opts);tipController=new TooltipController(options);initTracking();targetElements.each(function elementSetup(){var $this=$(this),dataPowertip=$this.data(DATA_POWERTIP),dataElem=$this.data(DATA_POWERTIPJQ),dataTarget=$this.data(DATA_POWERTIPTARGET),title=$this.attr("title");if(!dataPowertip&&!dataTarget&&!dataElem&&title){$this.data(DATA_POWERTIP,title);$this.data(DATA_ORIGINALTITLE,title);$this.removeAttr("title")}$this.data(DATA_DISPLAYCONTROLLER,new DisplayController($this,options,tipController))});if(!options.manual){$.each(options.openEvents,function(idx,evt){if($.inArray(evt,options.closeEvents)>-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference<options.intentSensitivity){cancelClose();closeAnyDelayed();tipController.showTip(element)}else{session.previousX=session.currentX;session.previousY=session.currentY;openTooltip()}}function cancelTimer(stopClose){hoverTimer=clearTimeout(hoverTimer);if(session.closeDelayTimeout&&myCloseDelay===session.closeDelayTimeout||stopClose){cancelClose()}}function cancelClose(){session.closeDelayTimeout=clearTimeout(session.closeDelayTimeout);session.delayInProgress=false}function closeAnyDelayed(){if(session.delayInProgress&&session.activeHover&&!session.activeHover.is(element)){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true)}}function repositionTooltip(){tipController.resetPosition(element)}this.show=openTooltip;this.hide=closeTooltip;this.cancel=cancelTimer;this.resetPosition=repositionTooltip}function PlacementCalculator(){function computePlacementCoords(element,placement,tipWidth,tipHeight,offset){var placementBase=placement.split("-")[0],coords=new CSSCoordinates,position;if(isSvgElement(element)){position=getSvgPlacement(element,placementBase)}else{position=getHtmlPlacement(element,placementBase)}switch(placement){case"n":coords.set("left",position.left-tipWidth/2);coords.set("bottom",session.windowHeight-position.top+offset);break;case"e":coords.set("left",position.left+offset);coords.set("top",position.top-tipHeight/2);break;case"s":coords.set("left",position.left-tipWidth/2);coords.set("top",position.top+offset);break;case"w":coords.set("top",position.top-tipHeight/2);coords.set("right",session.windowWidth-position.left+offset);break;case"nw":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"nw-alt":coords.set("left",position.left);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne":coords.set("left",position.left-20);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne-alt":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left);break;case"sw":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"sw-alt":coords.set("left",position.left);coords.set("top",position.top+offset);break;case"se":coords.set("left",position.left-20);coords.set("top",position.top+offset);break;case"se-alt":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left);break}return coords}function getHtmlPlacement(element,placement){var objectOffset=element.offset(),objectWidth=element.outerWidth(),objectHeight=element.outerHeight(),left,top;switch(placement){case"n":left=objectOffset.left+objectWidth/2;top=objectOffset.top;break;case"e":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight/2;break;case"s":left=objectOffset.left+objectWidth/2;top=objectOffset.top+objectHeight;break;case"w":left=objectOffset.left;top=objectOffset.top+objectHeight/2;break;case"nw":left=objectOffset.left;top=objectOffset.top;break;case"ne":left=objectOffset.left+objectWidth;top=objectOffset.top;break;case"sw":left=objectOffset.left;top=objectOffset.top+objectHeight;break;case"se":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight;break}return{top:top,left:left}}function getSvgPlacement(element,placement){var svgElement=element.closest("svg")[0],domElement=element[0],point=svgElement.createSVGPoint(),boundingBox=domElement.getBBox(),matrix=domElement.getScreenCTM(),halfWidth=boundingBox.width/2,halfHeight=boundingBox.height/2,placements=[],placementKeys=["nw","n","ne","e","se","s","sw","w"],coords,rotation,steps,x;function pushPlacement(){placements.push(point.matrixTransform(matrix))}point.x=boundingBox.x;point.y=boundingBox.y;pushPlacement();point.x+=halfWidth;pushPlacement();point.x+=halfWidth;pushPlacement();point.y+=halfHeight;pushPlacement();point.y+=halfHeight;pushPlacement();point.x-=halfWidth;pushPlacement();point.x-=halfWidth;pushPlacement();point.y-=halfHeight;pushPlacement();if(placements[0].y!==placements[1].y||placements[0].x!==placements[7].x){rotation=Math.atan2(matrix.b,matrix.a)*RAD2DEG;steps=Math.ceil((rotation%360-22.5)/45);if(steps<1){steps+=8}while(steps--){placementKeys.push(placementKeys.shift())}}for(x=0;x<placements.length;x++){if(placementKeys[x]===placement){coords=placements[x];break}}return{top:coords.y+session.scrollTop,left:coords.x+session.scrollLeft}}this.compute=computePlacementCoords}function TooltipController(options){var placementCalculator=new PlacementCalculator,tipElement=$("#"+options.popupId);if(tipElement.length===0){tipElement=$("<div/>",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.top<viewportTop||Math.abs(coords.bottom-session.windowHeight)-elementHeight<viewportTop){collisions|=Collision.top}if(coords.top+elementHeight>viewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.left<viewportLeft||coords.right+elementWidth>viewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right<viewportLeft){collisions|=Collision.right}return collisions}function countFlags(value){var count=0;while(value){value&=value-1;count++}return count}return $.powerTip});/*!
* jQuery UI Touch Punch 0.2.3
*
* Copyright 2011–2014, Dave Furfero
diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty
index bd5fdba..afa0f7d 100644
--- a/templates/latex/doxygen.sty
+++ b/templates/latex/doxygen.sty
@@ -3,14 +3,14 @@
% Packages used by this style file
\RequirePackage{alltt}
-\RequirePackage{array}
+%%\RequirePackage{array} %% moved to refman.tex due to workaround for LaTex 2019 version and unmaintained tabu package
\RequirePackage{calc}
\RequirePackage{float}
-\RequirePackage{ifthen}
+%%\RequirePackage{ifthen} %% moved to refman.tex due to workaround for LaTex 2019 version and unmaintained tabu package
\RequirePackage{verbatim}
\RequirePackage[table]{xcolor}
-\RequirePackage{longtable}
-\RequirePackage{tabu}
+\RequirePackage{longtable_doxygen}
+\RequirePackage{tabu_doxygen}
\RequirePackage{fancyvrb}
\RequirePackage{tabularx}
\RequirePackage{multirow}
@@ -306,16 +306,9 @@
% Used by @par and @paragraph
\newenvironment{DoxyParagraph}[1]{%
- \begin{list}{}{%
- \settowidth{\labelwidth}{40pt}%
- \setlength{\leftmargin}{\labelwidth+\labelsep}%
- \setlength{\parsep}{0pt}%
- \setlength{\itemsep}{-4pt}%
- \renewcommand{\makelabel}{\entrylabel}%
- }%
- \item[#1]%
+ \begin{DoxyDesc}{#1}%
}{%
- \end{list}%
+ \end{DoxyDesc}%
}
% Used by parameter lists
diff --git a/templates/latex/longtable_doxygen.sty b/templates/latex/longtable_doxygen.sty
new file mode 100755
index 0000000..a0eb314
--- /dev/null
+++ b/templates/latex/longtable_doxygen.sty
@@ -0,0 +1,448 @@
+%%
+%% This is file `longtable.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% longtable.dtx (with options: `package')
+%%
+%% This is a generated file.
+%%
+%% The source is maintained by the LaTeX Project team and bug
+%% reports for it can be opened at http://latex-project.org/bugs.html
+%% (but please observe conditions on bug reports sent to that address!)
+%%
+%% Copyright 1993-2016
+%% The LaTeX3 Project and any individual authors listed elsewhere
+%% in this file.
+%%
+%% This file was generated from file(s) of the Standard LaTeX `Tools Bundle'.
+%% --------------------------------------------------------------------------
+%%
+%% It may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3c
+%% of this license or (at your option) any later version.
+%% The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3c or later is part of all distributions of LaTeX
+%% version 2005/12/01 or later.
+%%
+%% This file may only be distributed together with a copy of the LaTeX
+%% `Tools Bundle'. You may however distribute the LaTeX `Tools Bundle'
+%% without such generated files.
+%%
+%% The list of all files belonging to the LaTeX `Tools Bundle' is
+%% given in the file `manifest.txt'.
+%%
+%% File: longtable.dtx Copyright (C) 1990-2001 David Carlisle
+\NeedsTeXFormat{LaTeX2e}[1995/06/01]
+\ProvidesPackage{longtable_doxygen}
+ [2014/10/28 v4.11 Multi-page Table package (DPC) - frozen version for doxygen]
+\def\LT@err{\PackageError{longtable}}
+\def\LT@warn{\PackageWarning{longtable}}
+\def\LT@final@warn{%
+ \AtEndDocument{%
+ \LT@warn{Table \@width s have changed. Rerun LaTeX.\@gobbletwo}}%
+ \global\let\LT@final@warn\relax}
+\DeclareOption{errorshow}{%
+ \def\LT@warn{\PackageInfo{longtable}}}
+\DeclareOption{pausing}{%
+ \def\LT@warn#1{%
+ \LT@err{#1}{This is not really an error}}}
+\DeclareOption{set}{}
+\DeclareOption{final}{}
+\ProcessOptions
+\newskip\LTleft \LTleft=\fill
+\newskip\LTright \LTright=\fill
+\newskip\LTpre \LTpre=\bigskipamount
+\newskip\LTpost \LTpost=\bigskipamount
+\newcount\LTchunksize \LTchunksize=20
+\let\c@LTchunksize\LTchunksize
+\newdimen\LTcapwidth \LTcapwidth=4in
+\newbox\LT@head
+\newbox\LT@firsthead
+\newbox\LT@foot
+\newbox\LT@lastfoot
+\newcount\LT@cols
+\newcount\LT@rows
+\newcounter{LT@tables}
+\newcounter{LT@chunks}[LT@tables]
+\ifx\c@table\undefined
+ \newcounter{table}
+ \def\fnum@table{\tablename~\thetable}
+\fi
+\ifx\tablename\undefined
+ \def\tablename{Table}
+\fi
+\newtoks\LT@p@ftn
+\mathchardef\LT@end@pen=30000
+\def\longtable{%
+ \par
+ \ifx\multicols\@undefined
+ \else
+ \ifnum\col@number>\@ne
+ \@twocolumntrue
+ \fi
+ \fi
+ \if@twocolumn
+ \LT@err{longtable not in 1-column mode}\@ehc
+ \fi
+ \begingroup
+ \@ifnextchar[\LT@array{\LT@array[x]}}
+\def\LT@array[#1]#2{%
+ \refstepcounter{table}\stepcounter{LT@tables}%
+ \if l#1%
+ \LTleft\z@ \LTright\fill
+ \else\if r#1%
+ \LTleft\fill \LTright\z@
+ \else\if c#1%
+ \LTleft\fill \LTright\fill
+ \fi\fi\fi
+ \let\LT@mcol\multicolumn
+ \let\LT@@tabarray\@tabarray
+ \let\LT@@hl\hline
+ \def\@tabarray{%
+ \let\hline\LT@@hl
+ \LT@@tabarray}%
+ \let\\\LT@tabularcr\let\tabularnewline\\%
+ \def\newpage{\noalign{\break}}%
+ \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}%
+ \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}%
+ \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption
+ \@tempdima\ht\strutbox
+ \let\@endpbox\LT@endpbox
+ \ifx\extrarowheight\@undefined
+ \let\@acol\@tabacol
+ \let\@classz\@tabclassz \let\@classiv\@tabclassiv
+ \def\@startpbox{\vtop\LT@startpbox}%
+ \let\@@startpbox\@startpbox
+ \let\@@endpbox\@endpbox
+ \let\LT@LL@FM@cr\@tabularcr
+ \else
+ \advance\@tempdima\extrarowheight
+ \col@sep\tabcolsep
+ \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr
+ \fi
+ \setbox\@arstrutbox\hbox{\vrule
+ \@height \arraystretch \@tempdima
+ \@depth \arraystretch \dp \strutbox
+ \@width \z@}%
+ \let\@sharp##\let\protect\relax
+ \begingroup
+ \@mkpream{#2}%
+ \xdef\LT@bchunk{%
+ \global\advance\c@LT@chunks\@ne
+ \global\LT@rows\z@\setbox\z@\vbox\bgroup
+ \LT@setprevdepth
+ \tabskip\LTleft \noexpand\halign to\hsize\bgroup
+ \tabskip\z@ \@arstrut \@preamble \tabskip\LTright \cr}%
+ \endgroup
+ \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols
+ \LT@make@row
+ \m@th\let\par\@empty
+ \everycr{}\lineskip\z@\baselineskip\z@
+ \LT@bchunk}
+\def\LT@no@pgbk#1[#2]{\penalty #1\@getpen{#2}\ifnum`{=0\fi}}
+\def\LT@start{%
+ \let\LT@start\endgraf
+ \endgraf\penalty\z@\vskip\LTpre
+ \dimen@\pagetotal
+ \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
+ \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi
+ \advance\dimen@ \ht\LT@foot
+ \dimen@ii\vfuzz
+ \vfuzz\maxdimen
+ \setbox\tw@\copy\z@
+ \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox
+ \setbox\tw@\vbox{\unvbox\tw@}%
+ \vfuzz\dimen@ii
+ \advance\dimen@ \ht
+ \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi
+ \advance\dimen@\dp
+ \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi
+ \advance\dimen@ -\pagegoal
+ \ifdim \dimen@>\z@\vfil\break\fi
+ \global\@colroom\@colht
+ \ifvoid\LT@foot\else
+ \advance\vsize-\ht\LT@foot
+ \global\advance\@colroom-\ht\LT@foot
+ \dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@
+ \maxdepth\z@
+ \fi
+ \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak
+ \output{\LT@output}}
+\def\endlongtable{%
+ \crcr
+ \noalign{%
+ \let\LT@entry\LT@entry@chop
+ \xdef\LT@save@row{\LT@save@row}}%
+ \LT@echunk
+ \LT@start
+ \unvbox\z@
+ \LT@get@widths
+ \if@filesw
+ {\let\LT@entry\LT@entry@write\immediate\write\@auxout{%
+ \gdef\expandafter\noexpand
+ \csname LT@\romannumeral\c@LT@tables\endcsname
+ {\LT@save@row}}}%
+ \fi
+ \ifx\LT@save@row\LT@@save@row
+ \else
+ \LT@warn{Column \@width s have changed\MessageBreak
+ in table \thetable}%
+ \LT@final@warn
+ \fi
+ \endgraf\penalty -\LT@end@pen
+ \endgroup
+ \global\@mparbottom\z@
+ \pagegoal\vsize
+ \endgraf\penalty\z@\addvspace\LTpost
+ \ifvoid\footins\else\insert\footins{}\fi}
+\def\LT@nofcols#1&{%
+ \futurelet\@let@token\LT@n@fcols}
+\def\LT@n@fcols{%
+ \advance\LT@cols\@ne
+ \ifx\@let@token\LT@nofcols
+ \expandafter\@gobble
+ \else
+ \expandafter\LT@nofcols
+ \fi}
+\def\LT@tabularcr{%
+ \relax\iffalse{\fi\ifnum0=`}\fi
+ \@ifstar
+ {\def\crcr{\LT@crcr\noalign{\nobreak}}\let\cr\crcr
+ \LT@t@bularcr}%
+ {\LT@t@bularcr}}
+\let\LT@crcr\crcr
+\let\LT@setprevdepth\relax
+\def\LT@t@bularcr{%
+ \global\advance\LT@rows\@ne
+ \ifnum\LT@rows=\LTchunksize
+ \gdef\LT@setprevdepth{%
+ \prevdepth\z@\global
+ \global\let\LT@setprevdepth\relax}%
+ \expandafter\LT@xtabularcr
+ \else
+ \ifnum0=`{}\fi
+ \expandafter\LT@LL@FM@cr
+ \fi}
+\def\LT@xtabularcr{%
+ \@ifnextchar[\LT@argtabularcr\LT@ntabularcr}
+\def\LT@ntabularcr{%
+ \ifnum0=`{}\fi
+ \LT@echunk
+ \LT@start
+ \unvbox\z@
+ \LT@get@widths
+ \LT@bchunk}
+\def\LT@argtabularcr[#1]{%
+ \ifnum0=`{}\fi
+ \ifdim #1>\z@
+ \unskip\@xargarraycr{#1}%
+ \else
+ \@yargarraycr{#1}%
+ \fi
+ \LT@echunk
+ \LT@start
+ \unvbox\z@
+ \LT@get@widths
+ \LT@bchunk}
+\def\LT@echunk{%
+ \crcr\LT@save@row\cr\egroup
+ \global\setbox\@ne\lastbox
+ \unskip
+ \egroup}
+\def\LT@entry#1#2{%
+ \ifhmode\@firstofone{&}\fi\omit
+ \ifnum#1=\c@LT@chunks
+ \else
+ \kern#2\relax
+ \fi}
+\def\LT@entry@chop#1#2{%
+ \noexpand\LT@entry
+ {\ifnum#1>\c@LT@chunks
+ 1}{0pt%
+ \else
+ #1}{#2%
+ \fi}}
+\def\LT@entry@write{%
+ \noexpand\LT@entry^^J%
+ \@spaces}
+\def\LT@kill{%
+ \LT@echunk
+ \LT@get@widths
+ \expandafter\LT@rebox\LT@bchunk}
+\def\LT@rebox#1\bgroup{%
+ #1\bgroup
+ \unvbox\z@
+ \unskip
+ \setbox\z@\lastbox}
+\def\LT@blank@row{%
+ \xdef\LT@save@row{\expandafter\LT@build@blank
+ \romannumeral\number\LT@cols 001 }}
+\def\LT@build@blank#1{%
+ \if#1m%
+ \noexpand\LT@entry{1}{0pt}%
+ \expandafter\LT@build@blank
+ \fi}
+\def\LT@make@row{%
+ \global\expandafter\let\expandafter\LT@save@row
+ \csname LT@\romannumeral\c@LT@tables\endcsname
+ \ifx\LT@save@row\relax
+ \LT@blank@row
+ \else
+ {\let\LT@entry\or
+ \if!%
+ \ifcase\expandafter\expandafter\expandafter\LT@cols
+ \expandafter\@gobble\LT@save@row
+ \or
+ \else
+ \relax
+ \fi
+ !%
+ \else
+ \aftergroup\LT@blank@row
+ \fi}%
+ \fi}
+\let\setlongtables\relax
+\def\LT@get@widths{%
+ \setbox\tw@\hbox{%
+ \unhbox\@ne
+ \let\LT@old@row\LT@save@row
+ \global\let\LT@save@row\@empty
+ \count@\LT@cols
+ \loop
+ \unskip
+ \setbox\tw@\lastbox
+ \ifhbox\tw@
+ \LT@def@row
+ \advance\count@\m@ne
+ \repeat}%
+ \ifx\LT@@save@row\@undefined
+ \let\LT@@save@row\LT@save@row
+ \fi}
+\def\LT@def@row{%
+ \let\LT@entry\or
+ \edef\@tempa{%
+ \ifcase\expandafter\count@\LT@old@row
+ \else
+ {1}{0pt}%
+ \fi}%
+ \let\LT@entry\relax
+ \xdef\LT@save@row{%
+ \LT@entry
+ \expandafter\LT@max@sel\@tempa
+ \LT@save@row}}
+\def\LT@max@sel#1#2{%
+ {\ifdim#2=\wd\tw@
+ #1%
+ \else
+ \number\c@LT@chunks
+ \fi}%
+ {\the\wd\tw@}}
+\def\LT@hline{%
+ \noalign{\ifnum0=`}\fi
+ \penalty\@M
+ \futurelet\@let@token\LT@@hline}
+\def\LT@@hline{%
+ \ifx\@let@token\hline
+ \global\let\@gtempa\@gobble
+ \gdef\LT@sep{\penalty-\@medpenalty\vskip\doublerulesep}%
+ \else
+ \global\let\@gtempa\@empty
+ \gdef\LT@sep{\penalty-\@lowpenalty\vskip-\arrayrulewidth}%
+ \fi
+ \ifnum0=`{\fi}%
+ \multispan\LT@cols
+ \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
+ \noalign{\LT@sep}%
+ \multispan\LT@cols
+ \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr
+ \noalign{\penalty\@M}%
+ \@gtempa}
+\def\LT@caption{%
+ \noalign\bgroup
+ \@ifnextchar[{\egroup\LT@c@ption\@firstofone}\LT@capti@n}
+\def\LT@c@ption#1[#2]#3{%
+ \LT@makecaption#1\fnum@table{#3}%
+ \def\@tempa{#2}%
+ \ifx\@tempa\@empty\else
+ {\let\\\space
+ \addcontentsline{lot}{table}{\protect\numberline{\thetable}{#2}}}%
+ \fi}
+\def\LT@capti@n{%
+ \@ifstar
+ {\egroup\LT@c@ption\@gobble[]}%
+ {\egroup\@xdblarg{\LT@c@ption\@firstofone}}}
+\def\LT@makecaption#1#2#3{%
+ \LT@mcol\LT@cols c{\hbox to\z@{\hss\parbox[t]\LTcapwidth{%
+ \sbox\@tempboxa{#1{#2: }#3}%
+ \ifdim\wd\@tempboxa>\hsize
+ #1{#2: }#3%
+ \else
+ \hbox to\hsize{\hfil\box\@tempboxa\hfil}%
+ \fi
+ \endgraf\vskip\baselineskip}%
+ \hss}}}
+\def\LT@output{%
+ \ifnum\outputpenalty <-\@Mi
+ \ifnum\outputpenalty > -\LT@end@pen
+ \LT@err{floats and marginpars not allowed in a longtable}\@ehc
+ \else
+ \setbox\z@\vbox{\unvbox\@cclv}%
+ \ifdim \ht\LT@lastfoot>\ht\LT@foot
+ \dimen@\pagegoal
+ \advance\dimen@-\ht\LT@lastfoot
+ \ifdim\dimen@<\ht\z@
+ \setbox\@cclv\vbox{\unvbox\z@\copy\LT@foot\vss}%
+ \@makecol
+ \@outputpage
+ \setbox\z@\vbox{\box\LT@head}%
+ \fi
+ \fi
+ \global\@colroom\@colht
+ \global\vsize\@colht
+ \vbox
+ {\unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi}%
+ \fi
+ \else
+ \setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}%
+ \@makecol
+ \@outputpage
+ \global\vsize\@colroom
+ \copy\LT@head\nobreak
+ \fi}
+\def\LT@end@hd@ft#1{%
+ \LT@echunk
+ \ifx\LT@start\endgraf
+ \LT@err
+ {Longtable head or foot not at start of table}%
+ {Increase LTchunksize}%
+ \fi
+ \setbox#1\box\z@
+ \LT@get@widths
+ \LT@bchunk}
+\def\endfirsthead{\LT@end@hd@ft\LT@firsthead}
+\def\endhead{\LT@end@hd@ft\LT@head}
+\def\endfoot{\LT@end@hd@ft\LT@foot}
+\def\endlastfoot{\LT@end@hd@ft\LT@lastfoot}
+\def\LT@startpbox#1{%
+ \bgroup
+ \let\@footnotetext\LT@p@ftntext
+ \setlength\hsize{#1}%
+ \@arrayparboxrestore
+ \vrule \@height \ht\@arstrutbox \@width \z@}
+\def\LT@endpbox{%
+ \@finalstrut\@arstrutbox
+ \egroup
+ \the\LT@p@ftn
+ \global\LT@p@ftn{}%
+ \hfil}
+\def\LT@p@ftntext#1{%
+ \edef\@tempa{\the\LT@p@ftn\noexpand\footnotetext[\the\c@footnote]}%
+ \global\LT@p@ftn\expandafter{\@tempa{#1}}}%
+
+\@namedef{ver@longtable.sty}{2014/10/28 v4.11 Multi-page Table package (DPC) - frozen version for doxygen}
+\endinput
+%%
+%% End of file `longtable.sty'.
diff --git a/templates/latex/tabu_doxygen.sty b/templates/latex/tabu_doxygen.sty
new file mode 100755
index 0000000..f760aca
--- /dev/null
+++ b/templates/latex/tabu_doxygen.sty
@@ -0,0 +1,2557 @@
+%%
+%% This is file `tabu.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% tabu.dtx (with options: `package')
+%%
+%% This is a generated file.
+%% Copyright (FC) 2010-2011 - lppl
+%%
+%% tabu : 2011/02/26 v2.8 - tabu : Flexible LaTeX tabulars
+%%
+%% **********************************************************************************************
+%% \begin{tabu} { preamble } => default target: \linewidth or \linegoal
+%% \begin{tabu} to <dimen>{ preamble } => target specified
+%% \begin{tabu} spread <dimen>{ preamble } => target relative to the ``natural width''
+%%
+%% tabu works in text and in math modes.
+%%
+%% X columns: automatic width ajustment + horizontal and vertical alignment
+%% \begin{tabu} { X[4c] X[1c] X[-2ml] }
+%%
+%% Horizontal lines and / or leaders:
+%% \hline\hline => double horizontal line
+%% \firsthline\hline => for nested tabulars
+%% \lasthline\hline => for nested tabulars
+%% \tabucline[line spec]{column-column} => ``funny'' lines (dash/leader)
+%% Automatic lines / leaders :
+%% \everyrow{\hline\hline}
+%%
+%% Vertical lines and / or leaders:
+%% \begin{tabu} { |[3pt red] X[4c] X[1c] X[-2ml] |[3pt blue] }
+%% \begin{tabu} { |[3pt red] X[4c] X[1c] X[-2ml] |[3pt on 2pt off 4pt blue] }
+%%
+%% Fixed vertical spacing adjustment:
+%% \extrarowheight=<dimen> \extrarowdepth=<dimen>
+%% or: \extrarowsep=<dimen> => may be prefixed by \global
+%%
+%% Dynamic vertical spacing adjustment:
+%% \abovetabulinesep=<dimen> \belowtabulinesep=<dimen>
+%% or: \tabulinesep=<dimen> => may be prefixed by \global
+%%
+%% delarray.sty shortcuts: in math and text modes
+%% \begin{tabu} .... \({ preamble }\)
+%%
+%% Algorithms reports:
+%% \tracingtabu=1 \tracingtabu=2
+%%
+%% **********************************************************************************************
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3 of this license or (at your option) any later
+%% version. The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This work consists of the main source file tabu.dtx
+%% and the derived files
+%% tabu.sty, tabu.pdf, tabu.ins
+%%
+%% tabu : Flexible LaTeX tabulars
+%% lppl copyright 2010-2011 by FC <florent.chervet@free.fr>
+%%
+
+\NeedsTeXFormat{LaTeX2e}[2005/12/01]
+\ProvidesPackage{tabu_doxygen}[2011/02/26 v2.8 - flexible LaTeX tabulars (FC), frozen version for doxygen]
+\RequirePackage{array}[2008/09/09]
+\RequirePackage{varwidth}[2009/03/30]
+\AtEndOfPackage{\tabu@AtEnd \let\tabu@AtEnd \@undefined}
+\let\tabu@AtEnd\@empty
+\def\TMP@EnsureCode#1={%
+ \edef\tabu@AtEnd{\tabu@AtEnd
+ \catcode#1 \the\catcode#1}%
+ \catcode#1=%
+}% \TMP@EnsureCode
+\TMP@EnsureCode 33 = 12 % !
+\TMP@EnsureCode 58 = 12 % : (for siunitx)
+\TMP@EnsureCode124 = 12 % |
+\TMP@EnsureCode 36 = 3 % $ = math shift
+\TMP@EnsureCode 38 = 4 % & = tab alignmment character
+\TMP@EnsureCode 32 = 10 % space
+\TMP@EnsureCode 94 = 7 % ^
+\TMP@EnsureCode 95 = 8 % _
+%% Constants --------------------------------------------------------
+\newcount \c@taburow \def\thetaburow {\number\c@taburow}
+\newcount \tabu@nbcols
+\newcount \tabu@cnt
+\newcount \tabu@Xcol
+\let\tabu@start \@tempcnta
+\let\tabu@stop \@tempcntb
+\newcount \tabu@alloc \tabu@alloc=\m@ne
+\newcount \tabu@nested
+\def\tabu@alloc@{\global\advance\tabu@alloc \@ne \tabu@nested\tabu@alloc}
+\newdimen \tabu@target
+\newdimen \tabu@spreadtarget
+\newdimen \tabu@naturalX
+\newdimen \tabucolX
+\let\tabu@DELTA \@tempdimc
+\let\tabu@thick \@tempdima
+\let\tabu@on \@tempdimb
+\let\tabu@off \@tempdimc
+\newdimen \tabu@Xsum
+\newdimen \extrarowdepth
+\newdimen \abovetabulinesep
+\newdimen \belowtabulinesep
+\newdimen \tabustrutrule \tabustrutrule \z@
+\newtoks \tabu@thebody
+\newtoks \tabu@footnotes
+\newsavebox \tabu@box
+\newsavebox \tabu@arstrutbox
+\newsavebox \tabu@hleads
+\newsavebox \tabu@vleads
+\newif \iftabu@colortbl
+\newif \iftabu@siunitx
+\newif \iftabu@measuring
+\newif \iftabu@spread
+\newif \iftabu@negcoef
+\newif \iftabu@everyrow
+\def\tabu@everyrowtrue {\global\let\iftabu@everyrow \iftrue}
+\def\tabu@everyrowfalse{\global\let\iftabu@everyrow \iffalse}
+\newif \iftabu@long
+\newif \iftabuscantokens
+\def\tabu@rescan {\tabu@verbatim \scantokens }
+%% Utilities (for internal usage) -----------------------------------
+\def\tabu@gobblespace #1 {#1}
+\def\tabu@gobbletoken #1#2{#1}
+\def\tabu@gobbleX{\futurelet\@let@token \tabu@gobblex}
+\def\tabu@gobblex{\if ^^J\noexpand\@let@token \expandafter\@gobble
+ \else\ifx \@sptoken\@let@token
+ \expandafter\tabu@gobblespace\expandafter\tabu@gobbleX
+ \fi\fi
+}% \tabu@gobblex
+\def\tabu@X{^^J}
+{\obeyspaces
+\global\let\tabu@spxiii= % saves an active space (for \ifx)
+\gdef\tabu@@spxiii{ }}
+\def\tabu@ifenvir {% only for \multicolumn
+ \expandafter\tabu@if@nvir\csname\@currenvir\endcsname
+}% \tabu@ifenvir
+\def\tabu@if@nvir #1{\csname @\ifx\tabu#1first\else
+ \ifx\longtabu#1first\else
+ second\fi\fi oftwo\endcsname
+}% \tabu@ifenvir
+\def\tabu@modulo #1#2{\numexpr\ifnum\numexpr#1=\z@ 0\else #1-(#1-(#2-1)/2)/(#2)*(#2)\fi}
+{\catcode`\&=3
+\gdef\tabu@strtrim #1{% #1 = control sequence to trim
+ \ifodd 1\ifx #1\@empty \else \ifx #1\space \else 0\fi \fi
+ \let\tabu@c@l@r \@empty \let#1\@empty
+ \else \expandafter \tabu@trimspaces #1&#1\@nnil
+ \fi
+}% \tabu@strtrim
+\gdef\tabu@trimspaces #1&#2\@nnil{\let\tabu@c@l@r=#2\tabu@firstspace .#1& &#2}%
+\gdef\tabu@firstspace #1#2#3 &{\tabu@lastspace #2#3&}
+\gdef\tabu@lastspace #1&#2&#3{\def #3{#1}%
+ \ifx #3\tabu@c@l@r \def\tabu@c@l@r{\protect\color{#1}}\expandafter\remove@to@nnil \fi
+ \tabu@trimspaces #1&#3\@nnil}
+}% \catcode
+\def\tabu@sanitizearg #1#2{{%
+ \csname \ifcsname if@safe@actives\endcsname % <babel>
+ @safe@activestrue\else
+ relax\fi \endcsname
+ \edef#2{#1}\tabu@strtrim#2\@onelevel@sanitize#2%
+ \expandafter}\expandafter\def\expandafter#2\expandafter{#2}%
+}% \tabu@sanitizearg
+\def\tabu@textbar #1{\begingroup \endlinechar\m@ne \scantokens{\def\:{|}}%
+ \expandafter\endgroup \expandafter#1\:% !!! semi simple group !!!
+}% \tabu@textbar
+\def\tabu@everyrow@bgroup{\iftabu@everyrow \begingroup \else \noalign{\ifnum0=`}\fi \fi}
+\def\tabu@everyrow@egroup{%
+ \iftabu@everyrow \expandafter \endgroup \the\toks@
+ \else \ifnum0=`{\fi}%
+ \fi
+}% \tabu@everyrow@egroup
+\def\tabu@arstrut {\global\setbox\@arstrutbox \hbox{\vrule
+ height \arraystretch \dimexpr\ht\strutbox+\extrarowheight
+ depth \arraystretch \dimexpr\dp\strutbox+\extrarowdepth
+ width \z@}%
+}% \tabu@arstrut
+\def\tabu@rearstrut {%
+ \@tempdima \arraystretch\dimexpr\ht\strutbox+\extrarowheight \relax
+ \@tempdimb \arraystretch\dimexpr\dp\strutbox+\extrarowdepth \relax
+ \ifodd 1\ifdim \ht\@arstrutbox=\@tempdima
+ \ifdim \dp\@arstrutbox=\@tempdimb 0 \fi\fi
+ \tabu@mkarstrut
+ \fi
+}% \tabu@rearstrut
+\def\tabu@@DBG #1{\ifdim\tabustrutrule>\z@ \color{#1}\fi}
+\def\tabu@DBG@arstrut {\global\setbox\@arstrutbox
+ \hbox to\z@{\hbox to\z@{\hss
+ {\tabu@DBG{cyan}\vrule
+ height \arraystretch \dimexpr\ht\strutbox+\extrarowheight
+ depth \z@
+ width \tabustrutrule}\kern-\tabustrutrule
+ {\tabu@DBG{pink}\vrule
+ height \z@
+ depth \arraystretch \dimexpr\dp\strutbox+\extrarowdepth
+ width \tabustrutrule}}}%
+}% \tabu@DBG@arstrut
+\def\tabu@save@decl{\toks\count@ \expandafter{\the\toks\expandafter\count@
+ \@nextchar}}%
+\def\tabu@savedecl{\ifcat$\d@llarend\else
+ \let\save@decl \tabu@save@decl \fi % no inversion of tokens in text mode
+}% \tabu@savedecl
+\def\tabu@finalstrut #1{\unskip\ifhmode\nobreak\fi\vrule height\z@ depth\z@ width\z@}
+\newcommand*\tabuDisableCommands {\g@addto@macro\tabu@trialh@@k }
+\let\tabu@trialh@@k \@empty
+\def\tabu@nowrite #1#{{\afterassignment}\toks@}
+\let\tabu@write\write
+\let\tabu@immediate\immediate
+\def\tabu@WRITE{\begingroup
+ \def\immediate\write{\aftergroup\endgroup
+ \tabu@immediate\tabu@write}%
+}% \tabu@WRITE
+\expandafter\def\expandafter\tabu@GenericError\expandafter{%
+ \expandafter\tabu@WRITE\GenericError}
+\def\tabu@warn{\tabu@WRITE\PackageWarning{tabu}}
+\def\tabu@noxfootnote [#1]{\@gobble}
+\def\tabu@nocolor #1#{\@gobble}
+\newcommand*\tabu@norowcolor[2][]{}
+\def\tabu@maybesiunitx #1{\def\tabu@temp{#1}%
+ \futurelet\@let@token \tabu@m@ybesiunitx}
+\def\tabu@m@ybesiunitx #1{\def\tabu@m@ybesiunitx {%
+ \ifx #1\@let@token \let\tabu@cellleft \@empty \let\tabu@cellright \@empty \fi
+ \tabu@temp}% \tabu@m@ybesiunitx
+}\expandafter\tabu@m@ybesiunitx \csname siunitx_table_collect_begin:Nn\endcsname
+\def\tabu@celllalign@def #1{\def\tabu@celllalign{\tabu@maybesiunitx{#1}}}%
+%% Fixed vertical spacing adjustment: \extrarowsep ------------------
+\newcommand*\extrarowsep{\edef\tabu@C@extra{\the\numexpr\tabu@C@extra+1}%
+ \iftabu@everyrow \aftergroup\tabu@Gextra
+ \else \aftergroup\tabu@n@Gextra
+ \fi
+ \@ifnextchar={\tabu@gobbletoken\tabu@extra} \tabu@extra
+}% \extrarowsep
+\def\tabu@extra {\@ifnextchar_%
+ {\tabu@gobbletoken{\tabu@setextra\extrarowheight \extrarowdepth}}
+ {\ifx ^\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setextra\extrarowdepth \extrarowheight}}%
+ \else \let\tabu@temp \@empty
+ \afterassignment \tabu@setextrasep \extrarowdepth
+ \fi \tabu@temp}%
+}% \tabu@extra
+\def\tabu@setextra #1#2{\def\tabu@temp{\tabu@extr@#1#2}\afterassignment\tabu@temp#2}
+\def\tabu@extr@ #1#2{\@ifnextchar^%
+ {\tabu@gobbletoken{\tabu@setextra\extrarowdepth \extrarowheight}}
+ {\ifx _\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setextra\extrarowheight \extrarowdepth}}%
+ \else \let\tabu@temp \@empty
+ \tabu@Gsave \tabu@G@extra \tabu@C@extra \extrarowheight \extrarowdepth
+ \fi \tabu@temp}%
+}% \tabu@extr@
+\def\tabu@setextrasep {\extrarowheight=\extrarowdepth
+ \tabu@Gsave \tabu@G@extra \tabu@C@extra \extrarowheight \extrarowdepth
+}% \tabu@setextrasep
+\def\tabu@Gextra{\ifx \tabu@G@extra\@empty \else {\tabu@Rextra}\fi}
+\def\tabu@n@Gextra{\ifx \tabu@G@extra\@empty \else \noalign{\tabu@Rextra}\fi}
+\def\tabu@Rextra{\tabu@Grestore \tabu@G@extra \tabu@C@extra}
+\let\tabu@C@extra \z@
+\let\tabu@G@extra \@empty
+%% Dynamic vertical spacing adjustment: \tabulinesep ----------------
+\newcommand*\tabulinesep{\edef\tabu@C@linesep{\the\numexpr\tabu@C@linesep+1}%
+ \iftabu@everyrow \aftergroup\tabu@Glinesep
+ \else \aftergroup\tabu@n@Glinesep
+ \fi
+ \@ifnextchar={\tabu@gobbletoken\tabu@linesep} \tabu@linesep
+}% \tabulinesep
+\def\tabu@linesep {\@ifnextchar_%
+ {\tabu@gobbletoken{\tabu@setsep\abovetabulinesep \belowtabulinesep}}
+ {\ifx ^\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setsep\belowtabulinesep \abovetabulinesep}}%
+ \else \let\tabu@temp \@empty
+ \afterassignment \tabu@setlinesep \abovetabulinesep
+ \fi \tabu@temp}%
+}% \tabu@linesep
+\def\tabu@setsep #1#2{\def\tabu@temp{\tabu@sets@p#1#2}\afterassignment\tabu@temp#2}
+\def\tabu@sets@p #1#2{\@ifnextchar^%
+ {\tabu@gobbletoken{\tabu@setsep\belowtabulinesep \abovetabulinesep}}
+ {\ifx _\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setsep\abovetabulinesep \belowtabulinesep}}%
+ \else \let\tabu@temp \@empty
+ \tabu@Gsave \tabu@G@linesep \tabu@C@linesep \abovetabulinesep \belowtabulinesep
+ \fi \tabu@temp}%
+}% \tabu@sets@p
+\def\tabu@setlinesep {\belowtabulinesep=\abovetabulinesep
+ \tabu@Gsave \tabu@G@linesep \tabu@C@linesep \abovetabulinesep \belowtabulinesep
+}% \tabu@setlinesep
+\def\tabu@Glinesep{\ifx \tabu@G@linesep\@empty \else {\tabu@Rlinesep}\fi}
+\def\tabu@n@Glinesep{\ifx \tabu@G@linesep\@empty \else \noalign{\tabu@Rlinesep}\fi}
+\def\tabu@Rlinesep{\tabu@Grestore \tabu@G@linesep \tabu@C@linesep}
+\let\tabu@C@linesep \z@
+\let\tabu@G@linesep \@empty
+%% \global\extrarowsep and \global\tabulinesep -------------------
+\def\tabu@Gsave #1#2#3#4{\xdef#1{#1%
+ \toks#2{\toks\the\currentgrouplevel{\global#3\the#3\global#4\the#4}}}%
+}% \tabu@Gsave
+\def\tabu@Grestore#1#2{%
+ \toks#2{}#1\toks\currentgrouplevel\expandafter{\expandafter}\the\toks#2\relax
+ \ifcat$\the\toks\currentgrouplevel$\else
+ \global\let#1\@empty \global\let#2\z@
+ \the\toks\currentgrouplevel
+ \fi
+}% \tabu@Grestore
+%% Setting code for every row ---------------------------------------
+\newcommand*\everyrow{\tabu@everyrow@bgroup
+ \tabu@start \z@ \tabu@stop \z@ \tabu@evrstartstop
+}% \everyrow
+\def\tabu@evrstartstop {\@ifnextchar^%
+ {\afterassignment \tabu@evrstartstop \tabu@stop=}%
+ {\ifx ^\@let@token
+ \afterassignment\tabu@evrstartstop \tabu@start=%
+ \else \afterassignment\tabu@everyr@w \toks@
+ \fi}%
+}% \tabu@evrstartstop
+\def\tabu@everyr@w {%
+ \xdef\tabu@everyrow{%
+ \noexpand\tabu@everyrowfalse
+ \let\noalign \relax
+ \noexpand\tabu@rowfontreset
+ \iftabu@colortbl \noexpand\tabu@rc@ \fi % \taburowcolors
+ \let\noexpand\tabu@docline \noexpand\tabu@docline@evr
+ \the\toks@
+ \noexpand\tabu@evrh@@k
+ \noexpand\tabu@rearstrut
+ \global\advance\c@taburow \@ne}%
+ \iftabu@everyrow \toks@\expandafter
+ {\expandafter\def\expandafter\tabu@evr@L\expandafter{\the\toks@}\ignorespaces}%
+ \else \xdef\tabu@evr@G{\the\toks@}%
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@everyr@w
+\def\tabu@evr {\def\tabu@evrh@@k} % for internal use only
+\tabu@evr{}
+%% line style and leaders -------------------------------------------
+\newcommand*\newtabulinestyle [1]{%
+ {\@for \@tempa :=#1\do{\expandafter\tabu@newlinestyle \@tempa==\@nil}}%
+}% \newtabulinestyle
+\def\tabu@newlinestyle #1=#2=#3\@nil{\tabu@getline {#2}%
+ \tabu@sanitizearg {#1}\@tempa
+ \ifodd 1\ifx \@tempa\@empty \ifdefined\tabu@linestyle@ 0 \fi\fi
+ \global\expandafter\let
+ \csname tabu@linestyle@\@tempa \endcsname =\tabu@thestyle \fi
+}% \tabu@newlinestyle
+\newcommand*\tabulinestyle [1]{\tabu@everyrow@bgroup \tabu@getline{#1}%
+ \iftabu@everyrow
+ \toks@\expandafter{\expandafter \def \expandafter
+ \tabu@ls@L\expandafter{\tabu@thestyle}\ignorespaces}%
+ \gdef\tabu@ls@{\tabu@ls@L}%
+ \else
+ \global\let\tabu@ls@G \tabu@thestyle
+ \gdef\tabu@ls@{\tabu@ls@G}%
+ \fi
+ \tabu@everyrow@egroup
+}% \tabulinestyle
+\newcommand*\taburulecolor{\tabu@everyrow@bgroup \tabu@textbar \tabu@rulecolor}
+\def\tabu@rulecolor #1{\toks@{}%
+ \def\tabu@temp #1##1#1{\tabu@ruledrsc{##1}}\@ifnextchar #1%
+ \tabu@temp
+ \tabu@rulearc
+}% \tabu@rulecolor
+\def\tabu@ruledrsc #1{\edef\tabu@temp{#1}\tabu@strtrim\tabu@temp
+ \ifx \tabu@temp\@empty \def\tabu@temp{\tabu@rule@drsc@ {}{}}%
+ \else \edef\tabu@temp{\noexpand\tabu@rule@drsc@ {}{\tabu@temp}}%
+ \fi
+ \tabu@temp
+}% \tabu@ruledrsc@
+\def\tabu@ruledrsc@ #1#{\tabu@rule@drsc@ {#1}}
+\def\tabu@rule@drsc@ #1#2{%
+ \iftabu@everyrow
+ \ifx \\#1#2\\\toks@{\let\CT@drsc@ \relax}%
+ \else \toks@{\def\CT@drsc@{\color #1{#2}}}%
+ \fi
+ \else
+ \ifx \\#1#2\\\global\let\CT@drsc@ \relax
+ \else \gdef\CT@drsc@{\color #1{#2}}%
+ \fi
+ \fi
+ \tabu@rulearc
+}% \tabu@rule@drsc@
+\def\tabu@rulearc #1#{\tabu@rule@arc@ {#1}}
+\def\tabu@rule@arc@ #1#2{%
+ \iftabu@everyrow
+ \ifx \\#1#2\\\toks@\expandafter{\the\toks@ \def\CT@arc@{}}%
+ \else \toks@\expandafter{\the\toks@ \def\CT@arc@{\color #1{#2}}}%
+ \fi
+ \toks@\expandafter{\the\toks@
+ \let\tabu@arc@L \CT@arc@
+ \let\tabu@drsc@L \CT@drsc@
+ \ignorespaces}%
+ \else
+ \ifx \\#1#2\\\gdef\CT@arc@{}%
+ \else \gdef\CT@arc@{\color #1{#2}}%
+ \fi
+ \global\let\tabu@arc@G \CT@arc@
+ \global\let\tabu@drsc@G \CT@drsc@
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@rule@arc@
+\def\taburowcolors {\tabu@everyrow@bgroup \@testopt \tabu@rowcolors 1}
+\def\tabu@rowcolors [#1]#2#{\tabu@rowc@lors{#1}{#2}}
+\def\tabu@rowc@lors #1#2#3{%
+ \toks@{}\@defaultunits \count@ =\number0#2\relax \@nnil
+ \@defaultunits \tabu@start =\number0#1\relax \@nnil
+ \ifnum \count@<\tw@ \count@=\tw@ \fi
+ \advance\tabu@start \m@ne
+ \ifnum \tabu@start<\z@ \tabu@start \z@ \fi
+ \tabu@rowcolorseries #3\in@..\in@ \@nnil
+}% \tabu@rowcolors
+\def\tabu@rowcolorseries #1..#2\in@ #3\@nnil {%
+ \ifx \in@#1\relax
+ \iftabu@everyrow \toks@{\def\tabu@rc@{}\let\tabu@rc@L \tabu@rc@}%
+ \else \gdef\tabu@rc@{}\global\let\tabu@rc@G \tabu@rc@
+ \fi
+ \else
+ \ifx \\#2\\\tabu@rowcolorserieserror \fi
+ \tabu@sanitizearg{#1}\tabu@temp
+ \tabu@sanitizearg{#2}\@tempa
+ \advance\count@ \m@ne
+ \iftabu@everyrow
+ \def\tabu@rc@ ##1##2##3##4{\def\tabu@rc@{%
+ \ifnum ##2=\c@taburow
+ \definecolorseries{tabu@rcseries@\the\tabu@nested}{rgb}{last}{##3}{##4}\fi
+ \ifnum \c@taburow<##2 \else
+ \ifnum \tabu@modulo {\c@taburow-##2}{##1+1}=\z@
+ \resetcolorseries[{##1}]{tabu@rcseries@\the\tabu@nested}\fi
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \rowcolor{tabu@rc@\the\tabu@nested}\fi}%
+ }\edef\x{\noexpand\tabu@rc@ {\the\count@}
+ {\the\tabu@start}
+ {\tabu@temp}
+ {\@tempa}%
+ }\x
+ \toks@\expandafter{\expandafter\def\expandafter\tabu@rc@\expandafter{\tabu@rc@}}%
+ \toks@\expandafter{\the\toks@ \let\tabu@rc@L \tabu@rc@ \ignorespaces}%
+ \else % inside \noalign
+ \definecolorseries{tabu@rcseries@\the\tabu@nested}{rgb}{last}{\tabu@temp}{\@tempa}%
+ \expandafter\resetcolorseries\expandafter[\the\count@]{tabu@rcseries@\the\tabu@nested}%
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \let\noalign \relax \rowcolor{tabu@rc@\the\tabu@nested}%
+ \def\tabu@rc@ ##1##2{\gdef\tabu@rc@{%
+ \ifnum \tabu@modulo {\c@taburow-##2}{##1+1}=\@ne
+ \resetcolorseries[{##1}]{tabu@rcseries@\the\tabu@nested}\fi
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \rowcolor{tabu@rc@\the\tabu@nested}}%
+ }\edef\x{\noexpand\tabu@rc@{\the\count@}{\the\c@taburow}}\x
+ \global\let\tabu@rc@G \tabu@rc@
+ \fi
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@rowcolorseries
+\tabuDisableCommands {\let\tabu@rc@ \@empty }
+\def\tabu@rowcolorserieserror {\PackageError{tabu}
+ {Invalid syntax for \string\taburowcolors
+ \MessageBreak Please look at the documentation!}\@ehd
+}% \tabu@rowcolorserieserror
+\newcommand*\tabureset {%
+ \tabulinesep=\z@ \extrarowsep=\z@ \extratabsurround=\z@
+ \tabulinestyle{}\everyrow{}\taburulecolor||{}\taburowcolors{}%
+}% \tabureset
+%% Parsing the line styles ------------------------------------------
+\def\tabu@getline #1{\begingroup
+ \csname \ifcsname if@safe@actives\endcsname % <babel>
+ @safe@activestrue\else
+ relax\fi \endcsname
+ \edef\tabu@temp{#1}\tabu@sanitizearg{#1}\@tempa
+ \let\tabu@thestyle \relax
+ \ifcsname tabu@linestyle@\@tempa \endcsname
+ \edef\tabu@thestyle{\endgroup
+ \def\tabu@thestyle{\expandafter\noexpand
+ \csname tabu@linestyle@\@tempa\endcsname}%
+ }\tabu@thestyle
+ \else \expandafter\tabu@definestyle \tabu@temp \@nil
+ \fi
+}% \tabu@getline
+\def\tabu@definestyle #1#2\@nil {\endlinechar \m@ne \makeatletter
+ \tabu@thick \maxdimen \tabu@on \maxdimen \tabu@off \maxdimen
+ \let\tabu@c@lon \@undefined \let\tabu@c@loff \@undefined
+ \ifodd 1\ifcat .#1\else\ifcat\relax #1\else 0\fi\fi % catcode 12 or non expandable cs
+ \def\tabu@temp{\tabu@getparam{thick}}%
+ \else \def\tabu@temp{\tabu@getparam{thick}\maxdimen}%
+ \fi
+ {%
+ \let\tabu@ \relax
+ \def\:{\obeyspaces \tabu@oXIII \tabu@commaXIII \edef\:}% (space active \: happy ;-))
+ \scantokens{\:{\tabu@temp #1#2 \tabu@\tabu@}}%
+ \expandafter}\expandafter
+ \def\expandafter\:\expandafter{\:}% line spec rewritten now ;-)
+ \def\;{\def\:}%
+ \scantokens\expandafter{\expandafter\;\expandafter{\:}}% space is now inactive (catcode 10)
+ \let\tabu@ \tabu@getcolor \:% all arguments are ready now ;-)
+ \ifdefined\tabu@c@lon \else \let\tabu@c@lon\@empty \fi
+ \ifx \tabu@c@lon\@empty \def\tabu@c@lon{\CT@arc@}\fi
+ \ifdefined\tabu@c@loff \else \let\tabu@c@loff \@empty \fi
+ \ifdim \tabu@on=\maxdimen \ifdim \tabu@off<\maxdimen
+ \tabu@on \tabulineon \fi\fi
+ \ifdim \tabu@off=\maxdimen \ifdim \tabu@on<\maxdimen
+ \tabu@off \tabulineoff \fi\fi
+ \ifodd 1\ifdim \tabu@off=\maxdimen \ifdim \tabu@on=\maxdimen 0 \fi\fi
+ \in@true % <leaders>
+ \else \in@false % <rule>
+ \fi
+ \ifdim\tabu@thick=\maxdimen \def\tabu@thick{\arrayrulewidth}%
+ \else \edef\tabu@thick{\the\tabu@thick}%
+ \fi
+ \edef \tabu@thestyle ##1##2{\endgroup
+ \def\tabu@thestyle{%
+ \ifin@ \noexpand\tabu@leadersstyle {\tabu@thick}
+ {\the\tabu@on}{##1}
+ {\the\tabu@off}{##2}%
+ \else \noexpand\tabu@rulesstyle
+ {##1\vrule width \tabu@thick}%
+ {##1\leaders \hrule height \tabu@thick \hfil}%
+ \fi}%
+ }\expandafter \expandafter
+ \expandafter \tabu@thestyle \expandafter
+ \expandafter \expandafter
+ {\expandafter\tabu@c@lon\expandafter}\expandafter{\tabu@c@loff}%
+}% \tabu@definestyle
+{\catcode`\O=\active \lccode`\O=`\o \catcode`\,=\active
+ \lowercase{\gdef\tabu@oXIII {\catcode`\o=\active \let O=\tabu@oxiii}}
+ \gdef\tabu@commaXIII {\catcode`\,=\active \let ,=\space}
+}% \catcode
+\def\tabu@oxiii #1{%
+ \ifcase \ifx n#1\z@ \else
+ \ifx f#1\@ne\else
+ \tw@ \fi\fi
+ \expandafter\tabu@onxiii
+ \or \expandafter\tabu@ofxiii
+ \else o%
+ \fi#1}%
+\def\tabu@onxiii #1#2{%
+ \ifcase \ifx !#2\tw@ \else
+ \ifcat.\noexpand#2\z@ \else
+ \ifx \tabu@spxiii#2\@ne\else
+ \tw@ \fi\fi\fi
+ \tabu@getparam{on}#2\expandafter\@gobble
+ \or \expandafter\tabu@onxiii % (space is active)
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}%
+\def\tabu@ofxiii #1#2{%
+ \ifx #2f\expandafter\tabu@offxiii
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}
+\def\tabu@offxiii #1#2{%
+ \ifcase \ifx !#2\tw@ \else
+ \ifcat.\noexpand#2\z@ \else
+ \ifx\tabu@spxiii#2\@ne \else
+ \tw@ \fi\fi\fi
+ \tabu@getparam{off}#2\expandafter\@gobble
+ \or \expandafter\tabu@offxiii % (space is active)
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}
+\def\tabu@getparam #1{\tabu@ \csname tabu@#1\endcsname=}
+\def\tabu@getcolor #1{% \tabu@ <- \tabu@getcolor after \edef
+ \ifx \tabu@#1\else % no more spec
+ \let\tabu@theparam=#1\afterassignment \tabu@getc@l@r #1\fi
+}% \tabu@getcolor
+\def\tabu@getc@l@r #1\tabu@ {%
+ \def\tabu@temp{#1}\tabu@strtrim \tabu@temp
+ \ifx \tabu@temp\@empty
+ \else%\ifcsname \string\color@\tabu@temp \endcsname % if the color exists
+ \ifx \tabu@theparam \tabu@off \let\tabu@c@loff \tabu@c@l@r
+ \else \let\tabu@c@lon \tabu@c@l@r
+ \fi
+ %\else \tabu@warncolour{\tabu@temp}%
+ \fi%\fi
+ \tabu@ % next spec
+}% \tabu@getc@l@r
+\def\tabu@warncolour #1{\PackageWarning{tabu}
+ {Color #1 is not defined. Default color used}%
+}% \tabu@warncolour
+\def\tabu@leadersstyle #1#2#3#4#5{\def\tabu@leaders{{#1}{#2}{#3}{#4}{#5}}%
+ \ifx \tabu@leaders\tabu@leaders@G \else
+ \tabu@LEADERS{#1}{#2}{#3}{#4}{#5}\fi
+}% \tabu@leadersstyle
+\def\tabu@rulesstyle #1#2{\let\tabu@leaders \@undefined
+ \gdef\tabu@thevrule{#1}\gdef\tabu@thehrule{#2}%
+}% \tabu@rulesstyle
+%% The leaders boxes ------------------------------------------------
+\def\tabu@LEADERS #1#2#3#4#5{%% width, dash, dash color, gap, gap color
+ {\let\color \tabu@color % => during trials -> \color = \tabu@nocolor
+ {% % but the leaders boxes should have colors !
+ \def\@therule{\vrule}\def\@thick{height}\def\@length{width}%
+ \def\@box{\hbox}\def\@unbox{\unhbox}\def\@elt{\wd}%
+ \def\@skip{\hskip}\def\@ss{\hss}\def\tabu@leads{\tabu@hleads}%
+ \tabu@l@@d@rs {#1}{#2}{#3}{#4}{#5}%
+ \global\let\tabu@thehleaders \tabu@theleaders
+ }%
+ {%
+ \def\@therule{\hrule}\def\@thick{width}\def\@length{height}%
+ \def\@box{\vbox}\def\@unbox{\unvbox}\def\@elt{\ht}%
+ \def\@skip{\vskip}\def\@ss{\vss}\def\tabu@leads{\tabu@vleads}%
+ \tabu@l@@d@rs {#1}{#2}{#3}{#4}{#5}%
+ \global\let\tabu@thevleaders \tabu@theleaders
+ }%
+ \gdef\tabu@leaders@G{{#1}{#2}{#3}{#4}{#5}}%
+ }%
+}% \tabu@LEADERS
+\def\tabu@therule #1#2{\@therule \@thick#1\@length\dimexpr#2/2 \@depth\z@}
+\def\tabu@l@@d@rs #1#2#3#4#5{%% width, dash, dash color, gap, gap color
+ \global\setbox \tabu@leads=\@box{%
+ {#3\tabu@therule{#1}{#2}}%
+ \ifx\\#5\\\@skip#4\else{#5\tabu@therule{#1}{#4*2}}\fi
+ {#3\tabu@therule{#1}{#2}}}%
+ \global\setbox\tabu@leads=\@box to\@elt\tabu@leads{\@ss
+ {#3\tabu@therule{#1}{#2}}\@unbox\tabu@leads}%
+ \edef\tabu@theleaders ##1{\def\noexpand\tabu@theleaders {%
+ {##1\tabu@therule{#1}{#2}}%
+ \xleaders \copy\tabu@leads \@ss
+ \tabu@therule{0pt}{-#2}{##1\tabu@therule{#1}{#2}}}%
+ }\tabu@theleaders{#3}%
+}% \tabu@l@@d@rs
+%% \tabu \endtabu \tabu* \longtabu \endlongtabu \longtabu* ----------
+\newcommand*\tabu {\tabu@longfalse
+ \ifmmode \def\tabu@ {\array}\def\endtabu {\endarray}%
+ \else \def\tabu@ {\tabu@tabular}\def\endtabu {\endtabular}\fi
+ \expandafter\let\csname tabu*\endcsname \tabu
+ \expandafter\def\csname endtabu*\endcsname{\endtabu}%
+ \tabu@spreadfalse \tabu@negcoeffalse \tabu@settarget
+}% {tabu}
+\let\tabu@tabular \tabular % <For LyX: some users redefine \tabular...>
+\expandafter\def\csname tabu*\endcsname{\tabuscantokenstrue \tabu}
+\newcommand*\longtabu {\tabu@longtrue
+ \ifmmode\PackageError{tabu}{longtabu not allowed in math mode}\fi
+ \def\tabu@{\longtable}\def\endlongtabu{\endlongtable}%
+ \LTchunksize=\@M
+ \expandafter\let\csname tabu*\endcsname \tabu
+ \expandafter\def\csname endlongtabu*\endcsname{\endlongtabu}%
+ \let\LT@startpbox \tabu@LT@startpbox % \everypar{ array struts }
+ \tabu@spreadfalse \tabu@negcoeffalse \tabu@settarget
+}% {longtabu}
+\expandafter\def\csname longtabu*\endcsname{\tabuscantokenstrue \longtabu}
+\def\tabu@nolongtabu{\PackageError{tabu}
+ {longtabu requires the longtable package}\@ehd}
+%% Read the target and then : \tabular or \@array ------------------
+\def\tabu@settarget {\futurelet\@let@token \tabu@sett@rget }
+\def\tabu@sett@rget {\tabu@target \z@
+ \ifcase \ifx \bgroup\@let@token \z@ \else
+ \ifx \@sptoken\@let@token \@ne \else
+ \if t\@let@token \tw@ \else
+ \if s\@let@token \thr@@\else
+ \z@\fi\fi\fi\fi
+ \expandafter\tabu@begin
+ \or \expandafter\tabu@gobblespace\expandafter\tabu@settarget
+ \or \expandafter\tabu@to
+ \or \expandafter\tabu@spread
+ \fi
+}% \tabu@sett@rget
+\def\tabu@to to{\def\tabu@halignto{to}\tabu@gettarget}
+\def\tabu@spread spread{\tabu@spreadtrue\def\tabu@halignto{spread}\tabu@gettarget}
+\def\tabu@gettarget {\afterassignment\tabu@linegoaltarget \tabu@target }
+\def\tabu@linegoaltarget {\futurelet\tabu@temp \tabu@linegoalt@rget }
+\def\tabu@linegoalt@rget {%
+ \ifx \tabu@temp\LNGL@setlinegoal
+ \LNGL@setlinegoal \expandafter \@firstoftwo \fi % @gobbles \LNGL@setlinegoal
+ \tabu@begin
+}% \tabu@linegoalt@rget
+\def\tabu@begin #1#{%
+ \iftabu@measuring \expandafter\tabu@nestedmeasure \fi
+ \ifdim \tabu@target=\z@ \let\tabu@halignto \@empty
+ \else \edef\tabu@halignto{\tabu@halignto\the\tabu@target}%
+ \fi
+ \@testopt \tabu@tabu@ \tabu@aligndefault #1\@nil
+}% \tabu@begin
+\long\def\tabu@tabu@ [#1]#2\@nil #3{\tabu@setup
+ \def\tabu@align {#1}\def\tabu@savedpream{\NC@find #3}%
+ \tabu@ [\tabu@align ]#2{#3\tabu@rewritefirst }%
+}% \tabu@tabu@
+\def\tabu@nestedmeasure {%
+ \ifodd 1\iftabu@spread \else \ifdim\tabu@target=\z@ \else 0 \fi\fi\relax
+ \tabu@spreadtrue
+ \else \begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}%
+ \expandafter\tabu@collectbody\expandafter\tabu@quickrule
+ \expandafter\endgroup
+ \fi
+}% \tabu@nestedmeasure
+\def\tabu@quickrule {\indent\vrule height\z@ depth\z@ width\tabu@target}
+%% \tabu@setup \tabu@init \tabu@indent
+\def\tabu@setup{\tabu@alloc@
+ \ifcase \tabu@nested
+ \ifmmode \else \iftabu@spread\else \ifdim\tabu@target=\z@
+ \let\tabu@afterendpar \par
+ \fi\fi\fi
+ \def\tabu@aligndefault{c}\tabu@init \tabu@indent
+ \else % <nested tabu>
+ \def\tabu@aligndefault{t}\let\tabudefaulttarget \linewidth
+ \fi
+ \let\tabu@thetarget \tabudefaulttarget \let\tabu@restored \@undefined
+ \edef\tabu@NC@list{\the\NC@list}\NC@list{\NC@do \tabu@rewritefirst}%
+ \everycr{}\let\@startpbox \tabu@startpbox % for nested tabu inside longtabu...
+ \let\@endpbox \tabu@endpbox % idem " " " " " "
+ \let\@tabarray \tabu@tabarray % idem " " " " " "
+ \tabu@setcleanup \tabu@setreset
+}% \tabu@setup
+\def\tabu@init{\tabu@starttimer \tabu@measuringfalse
+ \edef\tabu@hfuzz {\the\dimexpr\hfuzz+1sp}\global\tabu@footnotes{}%
+ \let\firsthline \tabu@firsthline \let\lasthline \tabu@lasthline
+ \let\firstline \tabu@firstline \let\lastline \tabu@lastline
+ \let\hline \tabu@hline \let\@xhline \tabu@xhline
+ \let\color \tabu@color \let\@arstrutbox \tabu@arstrutbox
+ \iftabu@colortbl\else\let\LT@@hline \tabu@LT@@hline \fi
+ \tabu@trivlist %<restore \\=\@normalcr inside lists>
+ \let\@footnotetext \tabu@footnotetext \let\@xfootnotetext \tabu@xfootnotetext
+ \let\@xfootnote \tabu@xfootnote \let\centering \tabu@centering
+ \let\raggedright \tabu@raggedright \let\raggedleft \tabu@raggedleft
+ \let\tabudecimal \tabu@tabudecimal \let\Centering \tabu@Centering
+ \let\RaggedRight \tabu@RaggedRight \let\RaggedLeft \tabu@RaggedLeft
+ \let\justifying \tabu@justifying \let\rowfont \tabu@rowfont
+ \let\fbox \tabu@fbox \let\color@b@x \tabu@color@b@x
+ \let\tabu@@everycr \everycr \let\tabu@@everypar \everypar
+ \let\tabu@prepnext@tokORI \prepnext@tok\let\prepnext@tok \tabu@prepnext@tok
+ \let\tabu@multicolumnORI\multicolumn \let\multicolumn \tabu@multicolumn
+ \let\tabu@startpbox \@startpbox % for nested tabu inside longtabu pfff !!!
+ \let\tabu@endpbox \@endpbox % idem " " " " " " "
+ \let\tabu@tabarray \@tabarray % idem " " " " " " "
+ \tabu@adl@fix \let\endarray \tabu@endarray % <fix> colortbl & arydshln (delarray)
+ \iftabu@colortbl\CT@everycr\expandafter{\expandafter\iftabu@everyrow \the\CT@everycr \fi}\fi
+}% \tabu@init
+\def\tabu@indent{% correction for indentation
+ \ifdim \parindent>\z@\ifx \linewidth\tabudefaulttarget
+ \everypar\expandafter{%
+ \the\everypar\everypar\expandafter{\the\everypar}%
+ \setbox\z@=\lastbox
+ \ifdim\wd\z@>\z@ \edef\tabu@thetarget
+ {\the\dimexpr -\wd\z@+\tabudefaulttarget}\fi
+ \box\z@}%
+ \fi\fi
+}% \tabu@indent
+\def\tabu@setcleanup {% saves last global assignments
+ \ifodd 1\ifmmode \else \iftabu@long \else 0\fi\fi\relax
+ \def\tabu@aftergroupcleanup{%
+ \def\tabu@aftergroupcleanup{\aftergroup\tabu@cleanup}}%
+ \else
+ \def\tabu@aftergroupcleanup{%
+ \aftergroup\aftergroup\aftergroup\tabu@cleanup
+ \let\tabu@aftergroupcleanup \relax}%
+ \fi
+ \let\tabu@arc@Gsave \tabu@arc@G
+ \let\tabu@arc@G \tabu@arc@L % <init>
+ \let\tabu@drsc@Gsave \tabu@drsc@G
+ \let\tabu@drsc@G \tabu@drsc@L % <init>
+ \let\tabu@ls@Gsave \tabu@ls@G
+ \let\tabu@ls@G \tabu@ls@L % <init>
+ \let\tabu@rc@Gsave \tabu@rc@G
+ \let\tabu@rc@G \tabu@rc@L % <init>
+ \let\tabu@evr@Gsave \tabu@evr@G
+ \let\tabu@evr@G \tabu@evr@L % <init>
+ \let\tabu@celllalign@save \tabu@celllalign
+ \let\tabu@cellralign@save \tabu@cellralign
+ \let\tabu@cellleft@save \tabu@cellleft
+ \let\tabu@cellright@save \tabu@cellright
+ \let\tabu@@celllalign@save \tabu@@celllalign
+ \let\tabu@@cellralign@save \tabu@@cellralign
+ \let\tabu@@cellleft@save \tabu@@cellleft
+ \let\tabu@@cellright@save \tabu@@cellright
+ \let\tabu@rowfontreset@save \tabu@rowfontreset
+ \let\tabu@@rowfontreset@save\tabu@@rowfontreset
+ \let\tabu@rowfontreset \@empty
+ \edef\tabu@alloc@save {\the\tabu@alloc}% restore at \tabu@reset
+ \edef\c@taburow@save {\the\c@taburow}%
+ \edef\tabu@naturalX@save {\the\tabu@naturalX}%
+ \let\tabu@naturalXmin@save \tabu@naturalXmin
+ \let\tabu@naturalXmax@save \tabu@naturalXmax
+ \let\tabu@mkarstrut@save \tabu@mkarstrut
+ \edef\tabu@clarstrut{%
+ \extrarowheight \the\dimexpr \ht\@arstrutbox-\ht\strutbox \relax
+ \extrarowdepth \the\dimexpr \dp\@arstrutbox-\dp\strutbox \relax
+ \let\noexpand\@arraystretch \@ne \noexpand\tabu@rearstrut}%
+}% \tabu@setcleanup
+\def\tabu@cleanup {\begingroup
+ \globaldefs\@ne \tabu@everyrowtrue
+ \let\tabu@arc@G \tabu@arc@Gsave
+ \let\CT@arc@ \tabu@arc@G
+ \let\tabu@drsc@G \tabu@drsc@Gsave
+ \let\CT@drsc@ \tabu@drsc@G
+ \let\tabu@ls@G \tabu@ls@Gsave
+ \let\tabu@ls@ \tabu@ls@G
+ \let\tabu@rc@G \tabu@rc@Gsave
+ \let\tabu@rc@ \tabu@rc@G
+ \let\CT@do@color \relax
+ \let\tabu@evr@G \tabu@evr@Gsave
+ \let\tabu@celllalign \tabu@celllalign@save
+ \let\tabu@cellralign \tabu@cellralign@save
+ \let\tabu@cellleft \tabu@cellleft@save
+ \let\tabu@cellright \tabu@cellright@save
+ \let\tabu@@celllalign \tabu@@celllalign@save
+ \let\tabu@@cellralign \tabu@@cellralign@save
+ \let\tabu@@cellleft \tabu@@cellleft@save
+ \let\tabu@@cellright \tabu@@cellright@save
+ \let\tabu@rowfontreset \tabu@rowfontreset@save
+ \let\tabu@@rowfontreset \tabu@@rowfontreset@save
+ \tabu@naturalX =\tabu@naturalX@save
+ \let\tabu@naturalXmax \tabu@naturalXmax@save
+ \let\tabu@naturalXmin \tabu@naturalXmin@save
+ \let\tabu@mkarstrut \tabu@mkarstrut@save
+ \c@taburow =\c@taburow@save
+ \ifcase \tabu@nested \tabu@alloc \m@ne\fi
+ \endgroup % <end of \globaldefs>
+ \ifcase \tabu@nested
+ \the\tabu@footnotes \global\tabu@footnotes{}%
+ \tabu@afterendpar \tabu@elapsedtime
+ \fi
+ \tabu@clarstrut
+ \everyrow\expandafter {\tabu@evr@G}%
+}% \tabu@cleanup
+\let\tabu@afterendpar \relax
+\def\tabu@setreset {%
+ \edef\tabu@savedparams {% \relax for \tabu@message@save
+ \ifmmode \col@sep \the\arraycolsep
+ \else \col@sep \the\tabcolsep \fi \relax
+ \arrayrulewidth \the\arrayrulewidth \relax
+ \doublerulesep \the\doublerulesep \relax
+ \extratabsurround \the\extratabsurround \relax
+ \extrarowheight \the\extrarowheight \relax
+ \extrarowdepth \the\extrarowdepth \relax
+ \abovetabulinesep \the\abovetabulinesep \relax
+ \belowtabulinesep \the\belowtabulinesep \relax
+ \def\noexpand\arraystretch{\arraystretch}%
+ \ifdefined\minrowclearance \minrowclearance\the\minrowclearance\relax\fi}%
+ \begingroup
+ \@temptokena\expandafter{\tabu@savedparams}% => only for \savetabu / \usetabu
+ \ifx \tabu@arc@L\relax \else \tabu@setsave \tabu@arc@L \fi
+ \ifx \tabu@drsc@L\relax \else \tabu@setsave \tabu@drsc@L \fi
+ \tabu@setsave \tabu@ls@L \tabu@setsave \tabu@evr@L
+ \expandafter \endgroup \expandafter
+ \def\expandafter\tabu@saved@ \expandafter{\the\@temptokena
+ \let\tabu@arc@G \tabu@arc@L
+ \let\tabu@drsc@G \tabu@drsc@L
+ \let\tabu@ls@G \tabu@ls@L
+ \let\tabu@rc@G \tabu@rc@L
+ \let\tabu@evr@G \tabu@evr@L}%
+ \def\tabu@reset{\tabu@savedparams
+ \tabu@everyrowtrue \c@taburow \z@
+ \let\CT@arc@ \tabu@arc@L
+ \let\CT@drsc@ \tabu@drsc@L
+ \let\tabu@ls@ \tabu@ls@L
+ \let\tabu@rc@ \tabu@rc@L
+ \global\tabu@alloc \tabu@alloc@save
+ \everyrow\expandafter{\tabu@evr@L}}%
+}% \tabu@reset
+\def\tabu@setsave #1{\expandafter\tabu@sets@ve #1\@nil{#1}}
+\long\def\tabu@sets@ve #1\@nil #2{\@temptokena\expandafter{\the\@temptokena \def#2{#1}}}
+%% The Rewritting Process -------------------------------------------
+\def\tabu@newcolumntype #1{%
+ \expandafter\tabu@new@columntype
+ \csname NC@find@\string#1\expandafter\endcsname
+ \csname NC@rewrite@\string#1\endcsname
+ {#1}%
+}% \tabu@newcolumntype
+\def\tabu@new@columntype #1#2#3{%
+ \def#1##1#3{\NC@{##1}}%
+ \let#2\relax \newcommand*#2%
+}% \tabu@new@columntype
+\def\tabu@privatecolumntype #1{%
+ \expandafter\tabu@private@columntype
+ \csname NC@find@\string#1\expandafter\endcsname
+ \csname NC@rewrite@\string#1\expandafter\endcsname
+ \csname tabu@NC@find@\string#1\expandafter\endcsname
+ \csname tabu@NC@rewrite@\string#1\endcsname
+ {#1}%
+}% \tabu@privatecolumntype
+\def\tabu@private@columntype#1#2#3#4{%
+ \g@addto@macro\tabu@privatecolumns{\let#1#3\let#2#4}%
+ \tabu@new@columntype#3#4%
+}% \tabu@private@columntype
+\let\tabu@privatecolumns \@empty
+\newcommand*\tabucolumn [1]{\expandafter \def \expandafter
+ \tabu@highprioritycolumns\expandafter{\tabu@highprioritycolumns
+ \NC@do #1}}%
+\let\tabu@highprioritycolumns \@empty
+%% The | ``column'' : rewriting process --------------------------
+\tabu@privatecolumntype |{\tabu@rewritevline}
+\newcommand*\tabu@rewritevline[1][]{\tabu@vlinearg{#1}%
+ \expandafter \NC@find \tabu@rewritten}
+\def\tabu@lines #1{%
+ \ifx|#1\else \tabu@privatecolumntype #1{\tabu@rewritevline}\fi
+ \NC@list\expandafter{\the\NC@list \NC@do #1}%
+}% \tabu@lines@
+\def\tabu@vlinearg #1{%
+ \ifx\\#1\\\def\tabu@thestyle {\tabu@ls@}%
+ \else\tabu@getline {#1}%
+ \fi
+ \def\tabu@rewritten ##1{\def\tabu@rewritten{!{##1\tabu@thevline}}%
+ }\expandafter\tabu@rewritten\expandafter{\tabu@thestyle}%
+ \expandafter \tabu@keepls \tabu@thestyle \@nil
+}% \tabu@vlinearg
+\def\tabu@keepls #1\@nil{%
+ \ifcat $\@cdr #1\@nil $%
+ \ifx \relax#1\else
+ \ifx \tabu@ls@#1\else
+ \let#1\relax
+ \xdef\tabu@mkpreambuffer{\tabu@mkpreambuffer
+ \tabu@savels\noexpand#1}\fi\fi\fi
+}% \tabu@keepls
+\def\tabu@thevline {\begingroup
+ \ifdefined\tabu@leaders
+ \setbox\@tempboxa=\vtop to\dimexpr
+ \ht\@arstrutbox+\dp\@arstrutbox{{\tabu@thevleaders}}%
+ \ht\@tempboxa=\ht\@arstrutbox \dp\@tempboxa=\dp\@arstrutbox
+ \box\@tempboxa
+ \else
+ \tabu@thevrule
+ \fi \endgroup
+}% \tabu@thevline
+\def\tabu@savels #1{%
+ \expandafter\let\csname\string#1\endcsname #1%
+ \expandafter\def\expandafter\tabu@reset\expandafter{\tabu@reset
+ \tabu@resetls#1}}%
+\def\tabu@resetls #1{\expandafter\let\expandafter#1\csname\string#1\endcsname}%
+%% \multicolumn inside tabu environment -----------------------------
+\tabu@newcolumntype \tabu@rewritemulticolumn{%
+ \aftergroup \tabu@endrewritemulticolumn % after \@mkpream group
+ \NC@list{\NC@do *}\tabu@textbar \tabu@lines
+ \tabu@savedecl
+ \tabu@privatecolumns
+ \NC@list\expandafter{\the\expandafter\NC@list \tabu@NC@list}%
+ \let\tabu@savels \relax
+ \NC@find
+}% \tabu@rewritemulticolumn
+\def\tabu@endrewritemulticolumn{\gdef\tabu@mkpreambuffer{}\endgroup}
+\def\tabu@multicolumn{\tabu@ifenvir \tabu@multic@lumn \tabu@multicolumnORI}
+\long\def\tabu@multic@lumn #1#2#3{\multispan{#1}\begingroup
+ \tabu@everyrowtrue
+ \NC@list{\NC@do \tabu@rewritemulticolumn}%
+ \expandafter\@gobbletwo % gobbles \multispan{#1}
+ \tabu@multicolumnORI{#1}{\tabu@rewritemulticolumn #2}%
+ {\iftabuscantokens \tabu@rescan \else \expandafter\@firstofone \fi
+ {#3}}%
+}% \tabu@multic@lumn
+%% The X column(s): rewriting process -----------------------------
+\tabu@privatecolumntype X[1][]{\begingroup \tabu@siunitx{\endgroup \tabu@rewriteX {#1}}}
+\def\tabu@nosiunitx #1{#1{}{}\expandafter \NC@find \tabu@rewritten }
+\def\tabu@siunitx #1{\@ifnextchar \bgroup
+ {\tabu@rewriteX@Ss{#1}}
+ {\tabu@nosiunitx{#1}}}
+\def\tabu@rewriteX@Ss #1#2{\@temptokena{}%
+ \@defaultunits \let\tabu@temp =#2\relax\@nnil
+ \ifodd 1\ifx S\tabu@temp \else \ifx s\tabu@temp \else 0 \fi\fi
+ \def\NC@find{\def\NC@find >####1####2<####3\relax{#1 {####1}{####3}%
+ }\expandafter\NC@find \the\@temptokena \relax
+ }\expandafter\NC@rewrite@S \@gobble #2\relax
+ \else \tabu@siunitxerror
+ \fi
+ \expandafter \NC@find \tabu@rewritten
+}% \tabu@rewriteX@Ss
+\def\tabu@siunitxerror {\PackageError{tabu}{Not a S nor s column !
+ \MessageBreak X column can only embed siunitx S or s columns}\@ehd
+}% \tabu@siunitxerror
+\def\tabu@rewriteX #1#2#3{\tabu@Xarg {#1}{#2}{#3}%
+ \iftabu@measuring
+ \else \tabu@measuringtrue % first X column found in the preamble
+ \let\@halignto \relax \let\tabu@halignto \relax
+ \iftabu@spread \tabu@spreadtarget \tabu@target \tabu@target \z@
+ \else \tabu@spreadtarget \z@ \fi
+ \ifdim \tabu@target=\z@
+ \setlength\tabu@target \tabu@thetarget
+ \tabu@message{\tabu@message@defaulttarget}%
+ \else \tabu@message{\tabu@message@target}\fi
+ \fi
+}% \tabu@rewriteX
+\def\tabu@rewriteXrestore #1#2#3{\let\@halignto \relax
+ \def\tabu@rewritten{l}}
+\def\tabu@Xarg #1#2#3{%
+ \advance\tabu@Xcol \@ne \let\tabu@Xlcr \@empty
+ \let\tabu@Xdisp \@empty \let\tabu@Xmath \@empty
+ \ifx\\#1\\% <shortcut when no option>
+ \def\tabu@rewritten{p}\tabucolX \p@ % <default coef = 1>
+ \else
+ \let\tabu@rewritten \@empty \let\tabu@temp \@empty \tabucolX \z@
+ \tabu@Xparse {}#1\relax
+ \fi
+ \tabu@Xrewritten{#2}{#3}%
+}% \tabu@Xarg
+\def\tabu@Xparse #1{\futurelet\@let@token \tabu@Xtest}
+\expandafter\def\expandafter\tabu@Xparsespace\space{\tabu@Xparse{}}
+\def\tabu@Xtest{%
+ \ifcase \ifx \relax\@let@token \z@ \else
+ \if ,\@let@token \m@ne\else
+ \if p\@let@token 1\else
+ \if m\@let@token 2\else
+ \if b\@let@token 3\else
+ \if l\@let@token 4\else
+ \if c\@let@token 5\else
+ \if r\@let@token 6\else
+ \if j\@let@token 7\else
+ \if L\@let@token 8\else
+ \if C\@let@token 9\else
+ \if R\@let@token 10\else
+ \if J\@let@token 11\else
+ \ifx \@sptoken\@let@token 12\else
+ \if .\@let@token 13\else
+ \if -\@let@token 13\else
+ \ifcat $\@let@token 14\else
+ 15\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\relax
+ \or \tabu@Xtype {p}%
+ \or \tabu@Xtype {m}%
+ \or \tabu@Xtype {b}%
+ \or \tabu@Xalign \raggedright\relax
+ \or \tabu@Xalign \centering\relax
+ \or \tabu@Xalign \raggedleft\relax
+ \or \tabu@Xalign \tabu@justify\relax
+ \or \tabu@Xalign \RaggedRight\raggedright
+ \or \tabu@Xalign \Centering\centering
+ \or \tabu@Xalign \RaggedLeft\raggedleft
+ \or \tabu@Xalign \justifying\tabu@justify
+ \or \expandafter \tabu@Xparsespace
+ \or \expandafter \tabu@Xcoef
+ \or \expandafter \tabu@Xm@th
+ \or \tabu@Xcoef{}%
+ \else\expandafter \tabu@Xparse
+ \fi
+}% \tabu@Xtest
+\def\tabu@Xalign #1#2{%
+ \ifx \tabu@Xlcr\@empty \else \PackageWarning{tabu}
+ {Duplicate horizontal alignment specification}\fi
+ \ifdefined#1\def\tabu@Xlcr{#1}\let#1\relax
+ \else \def\tabu@Xlcr{#2}\let#2\relax\fi
+ \expandafter\tabu@Xparse
+}% \tabu@Xalign
+\def\tabu@Xtype #1{%
+ \ifx \tabu@rewritten\@empty \else \PackageWarning{tabu}
+ {Duplicate vertical alignment specification}\fi
+ \def\tabu@rewritten{#1}\expandafter\tabu@Xparse
+}% \tabu@Xtype
+\def\tabu@Xcoef#1{\edef\tabu@temp{\tabu@temp#1}%
+ \afterassignment\tabu@Xc@ef \tabu@cnt\number\if-#10\fi
+}% \tabu@Xcoef
+\def\tabu@Xc@ef{\advance\tabucolX \tabu@temp\the\tabu@cnt\p@
+ \tabu@Xparse{}%
+}% \tabu@Xc@ef
+\def\tabu@Xm@th #1{\futurelet \@let@token \tabu@Xd@sp}
+\def\tabu@Xd@sp{\let\tabu@Xmath=$%
+ \ifx $\@let@token \def\tabu@Xdisp{\displaystyle}%
+ \expandafter\tabu@Xparse
+ \else \expandafter\tabu@Xparse\expandafter{\expandafter}%
+ \fi
+}% \tabu@Xd@sp
+\def\tabu@Xrewritten {%
+ \ifx \tabu@rewritten\@empty \def\tabu@rewritten{p}\fi
+ \ifdim \tabucolX<\z@ \tabu@negcoeftrue
+ \else\ifdim \tabucolX=\z@ \tabucolX \p@
+ \fi\fi
+ \edef\tabu@temp{{\the\tabu@Xcol}{\tabu@strippt\tabucolX}}%
+ \edef\tabu@Xcoefs{\tabu@Xcoefs \tabu@ \tabu@temp}%
+ \edef\tabu@rewritten ##1##2{\def\noexpand\tabu@rewritten{%
+ >{\tabu@Xlcr \ifx$\tabu@Xmath$\tabu@Xdisp\fi ##1}%
+ \tabu@rewritten {\tabu@hsize \tabu@temp}%
+ <{##2\ifx$\tabu@Xmath$\fi}}%
+ }\tabu@rewritten
+}% \tabu@Xrewritten
+\def\tabu@hsize #1#2{%
+ \ifdim #2\p@<\z@
+ \ifdim \tabucolX=\maxdimen \tabu@wd{#1}\else
+ \ifdim \tabu@wd{#1}<-#2\tabucolX \tabu@wd{#1}\else -#2\tabucolX\fi
+ \fi
+ \else #2\tabucolX
+ \fi
+}% \tabu@hsize
+%% \usetabu and \preamble: rewritting process ---------------------
+\tabu@privatecolumntype \usetabu [1]{%
+ \ifx\\#1\\\tabu@saveerr{}\else
+ \@ifundefined{tabu@saved@\string#1}
+ {\tabu@saveerr{#1}}
+ {\let\tabu@rewriteX \tabu@rewriteXrestore
+ \csname tabu@saved@\string#1\expandafter\endcsname\expandafter\@ne}%
+ \fi
+}% \NC@rewrite@\usetabu
+\tabu@privatecolumntype \preamble [1]{%
+ \ifx\\#1\\\tabu@saveerr{}\else
+ \@ifundefined{tabu@saved@\string#1}
+ {\tabu@saveerr{#1}}
+ {\csname tabu@saved@\string#1\expandafter\endcsname\expandafter\z@}%
+ \fi
+}% \NC@rewrite@\preamble
+%% Controlling the rewritting process -------------------------------
+\tabu@newcolumntype \tabu@rewritefirst{%
+ \iftabu@long \aftergroup \tabu@longpream % <the whole implementation is here !>
+ \else \aftergroup \tabu@pream
+ \fi
+ \let\tabu@ \relax \let\tabu@hsize \relax
+ \let\tabu@Xcoefs \@empty \let\tabu@savels \relax
+ \tabu@Xcol \z@ \tabu@cnt \tw@
+ \gdef\tabu@mkpreambuffer{\tabu@{}}\tabu@measuringfalse
+ \global\setbox\@arstrutbox \box\@arstrutbox
+ \NC@list{\NC@do *}\tabu@textbar \tabu@lines
+ \NC@list\expandafter{\the\NC@list \NC@do X}%
+ \iftabu@siunitx % <siunitx S and s columns>
+ \NC@list\expandafter{\the\NC@list \NC@do S\NC@do s}\fi
+ \NC@list\expandafter{\the\expandafter\NC@list \tabu@highprioritycolumns}%
+ \expandafter\def\expandafter\tabu@NC@list\expandafter{%
+ \the\expandafter\NC@list \tabu@NC@list}% % * | X S <original>
+ \NC@list\expandafter{\expandafter \NC@do \expandafter\usetabu
+ \expandafter \NC@do \expandafter\preamble
+ \the\NC@list \NC@do \tabu@rewritemiddle
+ \NC@do \tabu@rewritelast}%
+ \tabu@savedecl
+ \tabu@privatecolumns
+ \edef\tabu@prev{\the\@temptokena}\NC@find \tabu@rewritemiddle
+}% NC@rewrite@\tabu@rewritefirst
+\tabu@newcolumntype \tabu@rewritemiddle{%
+ \edef\tabu@temp{\the\@temptokena}\NC@find \tabu@rewritelast
+}% \NC@rewrite@\tabu@rewritemiddle
+\tabu@newcolumntype \tabu@rewritelast{%
+ \ifx \tabu@temp\tabu@prev \advance\tabu@cnt \m@ne
+ \NC@list\expandafter{\tabu@NC@list \NC@do \tabu@rewritemiddle
+ \NC@do \tabu@rewritelast}%
+ \else \let\tabu@prev\tabu@temp
+ \fi
+ \ifcase \tabu@cnt \expandafter\tabu@endrewrite
+ \else \expandafter\NC@find \expandafter\tabu@rewritemiddle
+ \fi
+}% \NC@rewrite@\tabu@rewritelast
+%% Choosing the strategy --------------------------------------------
+\def\tabu@endrewrite {%
+ \let\tabu@temp \NC@find
+ \ifx \@arrayright\relax \let\@arrayright \@empty \fi
+ \count@=%
+ \ifx \@finalstrut\tabu@finalstrut \z@ % outer in mode 0 print
+ \iftabu@measuring
+ \xdef\tabu@mkpreambuffer{\tabu@mkpreambuffer
+ \tabu@target \csname tabu@\the\tabu@nested.T\endcsname
+ \tabucolX \csname tabu@\the\tabu@nested.X\endcsname
+ \edef\@halignto {\ifx\@arrayright\@empty to\tabu@target\fi}}%
+ \fi
+ \else\iftabu@measuring 4 % X columns
+ \xdef\tabu@mkpreambuffer{\tabu@{\tabu@mkpreambuffer
+ \tabu@target \the\tabu@target
+ \tabu@spreadtarget \the\tabu@spreadtarget}%
+ \def\noexpand\tabu@Xcoefs{\tabu@Xcoefs}%
+ \edef\tabu@halignto{\ifx \@arrayright\@empty to\tabu@target\fi}}%
+ \let\tabu@Xcoefs \relax
+ \else\ifcase\tabu@nested \thr@@ % outer, no X
+ \global\let\tabu@afterendpar \relax
+ \else \@ne % inner, no X, outer in mode 1 or 2
+ \fi
+ \ifdefined\tabu@usetabu
+ \else \ifdim\tabu@target=\z@
+ \else \let\tabu@temp \tabu@extracolsep
+ \fi\fi
+ \fi
+ \fi
+ \xdef\tabu@mkpreambuffer{\count@ \the\count@ \tabu@mkpreambuffer}%
+ \tabu@temp
+}% \tabu@endrewrite
+\def\tabu@extracolsep{\@defaultunits \expandafter\let
+ \expandafter\tabu@temp \expandafter=\the\@temptokena \relax\@nnil
+ \ifx \tabu@temp\@sptoken
+ \expandafter\tabu@gobblespace \expandafter\tabu@extracolsep
+ \else
+ \edef\tabu@temp{\noexpand\NC@find
+ \if |\noexpand\tabu@temp @%
+ \else\if !\noexpand\tabu@temp @%
+ \else !%
+ \fi\fi
+ {\noexpand\extracolsep\noexpand\@flushglue}}%
+ \fi
+ \tabu@temp
+}% \tabu@extrac@lsep
+%% Implementing the strategy ----------------------------------------
+\long\def\tabu@pream #1\@preamble {%
+ \let\tabu@ \tabu@@ \tabu@mkpreambuffer \tabu@aftergroupcleanup
+ \NC@list\expandafter {\tabu@NC@list}% in case of nesting...
+ \ifdefined\tabu@usetabu \tabu@usetabu \tabu@target \z@ \fi
+ \let\tabu@savedpreamble \@preamble
+ \global\let\tabu@elapsedtime \relax
+ \tabu@thebody ={#1\tabu@aftergroupcleanup}%
+ \tabu@thebody =\expandafter{\the\expandafter\tabu@thebody
+ \@preamble}%
+ \edef\tabuthepreamble {\the\tabu@thebody}% ( no @ allowed for \scantokens )
+ \tabu@select
+}% \tabu@pream
+\long\def\tabu@longpream #1\LT@bchunk #2\LT@bchunk{%
+ \let\tabu@ \tabu@@ \tabu@mkpreambuffer \tabu@aftergroupcleanup
+ \NC@list\expandafter {\tabu@NC@list}% in case of nesting...
+ \let\tabu@savedpreamble \@preamble
+ \global\let\tabu@elapsedtime \relax
+ \tabu@thebody ={#1\LT@bchunk #2\tabu@aftergroupcleanup \LT@bchunk}%
+ \edef\tabuthepreamble {\the\tabu@thebody}% ( no @ allowed for \scantokens )
+ \tabu@select
+}% \tabu@longpream
+\def\tabu@select {%
+ \ifnum\tabu@nested>\z@ \tabuscantokensfalse \fi
+ \ifnum \count@=\@ne \iftabu@measuring \count@=\tw@ \fi\fi
+ \ifcase \count@
+ \global\let\tabu@elapsedtime \relax
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble % vertical adjustment (inheritated from outer)
+ \or % exit in vertical measure + struts per cell because no X and outer in mode 3
+ \tabu@evr{\tabu@verticalinit}\tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble
+ \or % exit without measure because no X and outer in mode 4
+ \tabu@evr{}\tabu@celllalign@def{}\let\tabu@cellralign \@empty
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble
+ \else % needs trials
+ \tabu@evr{}\tabu@celllalign@def{}\let\tabu@cellralign \@empty
+ \tabu@savecounters
+ \expandafter \tabu@setstrategy
+ \fi
+}% \tabu@select
+\def\tabu@@ {\gdef\tabu@mkpreambuffer}
+%% Protections to set up before trials ------------------------------
+\def\tabu@setstrategy {\begingroup % <trials group>
+ \tabu@trialh@@k \tabu@cnt \z@ % number of trials
+ \hbadness \@M \let\hbadness \@tempcnta
+ \hfuzz \maxdimen \let\hfuzz \@tempdima
+ \let\write \tabu@nowrite\let\GenericError \tabu@GenericError
+ \let\savetabu \@gobble \let\tabudefaulttarget \linewidth
+ \let\@footnotetext \@gobble \let\@xfootnote \tabu@xfootnote
+ \let\color \tabu@nocolor\let\rowcolor \tabu@norowcolor
+ \let\tabu@aftergroupcleanup \relax % only after the last trial
+ \tabu@mkpreambuffer
+ \ifnum \count@>\thr@@ \let\@halignto \@empty \tabucolX@init
+ \def\tabu@lasttry{\m@ne\p@}\fi
+ \begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}\iftabuscantokens \endlinechar=10 \obeyspaces \fi %
+ \tabu@collectbody \tabu@strategy %
+}% \tabu@setstrategy
+\def\tabu@savecounters{%
+ \def\@elt ##1{\csname c@##1\endcsname\the\csname c@##1\endcsname}%
+ \edef\tabu@clckpt {\begingroup \globaldefs=\@ne \cl@@ckpt \endgroup}\let\@elt \relax
+}% \tabu@savecounters
+\def\tabucolX@init {% \tabucolX <= \tabu@target / (sum coefs > 0)
+ \dimen@ \z@ \tabu@Xsum \z@ \tabucolX \z@ \let\tabu@ \tabu@Xinit \tabu@Xcoefs
+ \ifdim \dimen@>\z@
+ \@tempdima \dimexpr \tabu@target *\p@/\dimen@ + \tabu@hfuzz\relax
+ \ifdim \tabucolX<\@tempdima \tabucolX \@tempdima \fi
+ \fi
+}% \tabucolX@init
+\def\tabu@Xinit #1#2{\tabu@Xcol #1 \advance \tabu@Xsum
+ \ifdim #2\p@>\z@ #2\p@ \advance\dimen@ #2\p@
+ \else -#2\p@ \tabu@negcoeftrue
+ \@tempdima \dimexpr \tabu@target*\p@/\dimexpr-#2\p@\relax \relax
+ \ifdim \tabucolX<\@tempdima \tabucolX \@tempdima \fi
+ \tabu@wddef{#1}{0pt}%
+ \fi
+}% \tabu@Xinit
+%% Collecting the environment body ----------------------------------
+\long\def\tabu@collectbody #1#2\end #3{%
+ \edef\tabu@stack{\tabu@pushbegins #2\begin\end\expandafter\@gobble\tabu@stack}%
+ \ifx \tabu@stack\@empty
+ \toks@\expandafter{\expandafter\tabu@thebody\expandafter{\the\toks@ #2}%
+ \def\tabu@end@envir{\end{#3}}%
+ \iftabuscantokens
+ \iftabu@long \def\tabu@endenvir {\end{#3}\tabu@gobbleX}%
+ \else \def\tabu@endenvir {\let\endarray \@empty
+ \end{#3}\tabu@gobbleX}%
+ \fi
+ \else \def\tabu@endenvir {\end{#3}}\fi}%
+ \let\tabu@collectbody \tabu@endofcollect
+ \else\def\tabu@temp{#3}%
+ \ifx \tabu@temp\@empty \toks@\expandafter{\the\toks@ #2\end }%
+ \else \ifx\tabu@temp\tabu@@spxiii \toks@\expandafter{\the\toks@ #2\end #3}%
+ \else \ifx\tabu@temp\tabu@X \toks@\expandafter{\the\toks@ #2\end #3}%
+ \else \toks@\expandafter{\the\toks@ #2\end{#3}}%
+ \fi\fi\fi
+ \fi
+ \tabu@collectbody{#1}%
+}% \tabu@collectbody
+\long\def\tabu@pushbegins#1\begin#2{\ifx\end#2\else b\expandafter\tabu@pushbegins\fi}%
+\def\tabu@endofcollect #1{\ifnum0=`{}\fi
+ \expandafter\endgroup \the\toks@ #1%
+}% \tabu@endofcollect
+%% The trials: switching between strategies -------------------------
+\def\tabu@strategy {\relax % stops \count@ assignment !
+ \ifcase\count@ % case 0 = print with vertical adjustment (outer is finished)
+ \expandafter \tabu@endoftrials
+ \or % case 1 = exit in vertical measure (outer in mode 3)
+ \expandafter\xdef\csname tabu@\the\tabu@nested.T\endcsname{\the\tabu@target}%
+ \expandafter\xdef\csname tabu@\the\tabu@nested.X\endcsname{\the\tabucolX}%
+ \expandafter \tabu@endoftrials
+ \or % case 2 = exit with a rule replacing the table (outer in mode 4)
+ \expandafter \tabu@quickend
+ \or % case 3 = outer is in mode 3 because of no X
+ \begingroup
+ \tabu@evr{\tabu@verticalinit}\tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \expandafter \tabu@measuring
+ \else % case 4 = horizontal measure
+ \begingroup
+ \global\let\tabu@elapsedtime \tabu@message@etime
+ \long\def\multicolumn##1##2##3{\multispan{##1}}%
+ \let\tabu@startpboxORI \@startpbox
+ \iftabu@spread
+ \def\tabu@naturalXmax {\z@}%
+ \let\tabu@naturalXmin \tabu@naturalXmax
+ \tabu@evr{\global\tabu@naturalX \z@}%
+ \let\@startpbox \tabu@startpboxmeasure
+ \else\iftabu@negcoef
+ \let\@startpbox \tabu@startpboxmeasure
+ \else \let\@startpbox \tabu@startpboxquick
+ \fi\fi
+ \expandafter \tabu@measuring
+ \fi
+}% \tabu@strategy
+\def\tabu@measuring{\expandafter \tabu@trial \expandafter
+ \count@ \the\count@ \tabu@endtrial
+}% \tabu@measuring
+\def\tabu@trial{\iftabu@long \tabu@longtrial \else \tabu@shorttrial \fi}
+\def\tabu@shorttrial {\setbox\tabu@box \hbox\bgroup \tabu@seteverycr
+ \ifx \tabu@savecounters\relax \else
+ \let\tabu@savecounters \relax \tabu@clckpt \fi
+ $\iftabuscantokens \tabu@rescan \else \expandafter\@secondoftwo \fi
+ \expandafter{\expandafter \tabuthepreamble
+ \the\tabu@thebody
+ \csname tabu@adl@endtrial\endcsname
+ \endarray}$\egroup % got \tabu@box
+}% \tabu@shorttrial
+\def\tabu@longtrial {\setbox\tabu@box \hbox\bgroup \tabu@seteverycr
+ \ifx \tabu@savecounters\relax \else
+ \let\tabu@savecounters \relax \tabu@clckpt \fi
+ \iftabuscantokens \tabu@rescan \else \expandafter\@secondoftwo \fi
+ \expandafter{\expandafter \tabuthepreamble
+ \the\tabu@thebody
+ \tabuendlongtrial}\egroup % got \tabu@box
+}% \tabu@longtrial
+\def\tabuendlongtrial{% no @ allowed for \scantokens
+ \LT@echunk \global\setbox\@ne \hbox{\unhbox\@ne}\kern\wd\@ne
+ \LT@get@widths
+}% \tabuendlongtrial
+\def\tabu@adl@endtrial{% <arydshln in nested trials - problem for global column counters!>
+ \crcr \noalign{\global\adl@ncol \tabu@nbcols}}% anything global is crap, junky and fails !
+\def\tabu@seteverycr {\tabu@reset
+ \everycr \expandafter{\the\everycr \tabu@everycr}%
+ \let\everycr \tabu@noeverycr % <for ialign>
+}% \tabu@seteverycr
+\def\tabu@noeverycr{{\aftergroup\tabu@restoreeverycr \afterassignment}\toks@}
+\def\tabu@restoreeverycr {\let\everycr \tabu@@everycr}
+\def\tabu@everycr {\iftabu@everyrow \noalign{\tabu@everyrow}\fi}
+\def\tabu@endoftrials {%
+ \iftabuscantokens \expandafter\@firstoftwo
+ \else \expandafter\@secondoftwo
+ \fi
+ {\expandafter \tabu@closetrialsgroup \expandafter
+ \tabu@rescan \expandafter{%
+ \expandafter\tabuthepreamble
+ \the\expandafter\tabu@thebody
+ \iftabu@long \else \endarray \fi}}
+ {\expandafter\tabu@closetrialsgroup \expandafter
+ \tabuthepreamble
+ \the\tabu@thebody}%
+ \tabu@endenvir % Finish !
+}% \tabu@endoftrials
+\def\tabu@closetrialsgroup {%
+ \toks@\expandafter{\tabu@endenvir}%
+ \edef\tabu@bufferX{\endgroup
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target
+ \tabu@cnt \the\tabu@cnt
+ \def\noexpand\tabu@endenvir{\the\toks@}%
+ %Quid de \@halignto = \tabu@halignto ??
+ }% \tabu@bufferX
+ \tabu@bufferX
+ \ifcase\tabu@nested % print out (outer in mode 0)
+ \global\tabu@cnt \tabu@cnt
+ \tabu@evr{\tabu@verticaldynamicadjustment}%
+ \tabu@celllalign@def{\everypar{}}\let\tabu@cellralign \@empty
+ \let\@finalstrut \tabu@finalstrut
+ \else % vertical measure of nested tabu
+ \tabu@evr{\tabu@verticalinit}%
+ \tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \fi
+ \tabu@clckpt \let\@halignto \tabu@halignto
+ \let\@halignto \@empty
+ \tabu@seteverycr
+ \ifdim \tabustrutrule>\z@ \ifnum\tabu@nested=\z@
+ \setbox\@arstrutbox \box\voidb@x % force \@arstrutbox to be rebuilt (visible struts)
+ \fi\fi
+}% \tabu@closetrialsgroup
+\def\tabu@quickend {\expandafter \endgroup \expandafter
+ \tabu@target \the\tabu@target \tabu@quickrule
+ \let\endarray \relax \tabu@endenvir
+}% \tabu@quickend
+\def\tabu@endtrial {\relax % stops \count@ assignment !
+ \ifcase \count@ \tabu@err % case 0 = impossible here
+ \or \tabu@err % case 1 = impossible here
+ \or \tabu@err % case 2 = impossible here
+ \or % case 3 = outer goes into mode 0
+ \def\tabu@bufferX{\endgroup}\count@ \z@
+ \else % case 4 = outer goes into mode 3
+ \iftabu@spread \tabu@spreadarith % inner into mode 1 (outer in mode 3)
+ \else \tabu@arith % or 2 (outer in mode 4)
+ \fi
+ \count@=%
+ \ifcase\tabu@nested \thr@@ % outer goes into mode 3
+ \else\iftabu@measuring \tw@ % outer is in mode 4
+ \else \@ne % outer is in mode 3
+ \fi\fi
+ \edef\tabu@bufferX{\endgroup
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target}%
+ \fi
+ \expandafter \tabu@bufferX \expandafter
+ \count@ \the\count@ \tabu@strategy
+}% \tabu@endtrial
+\def\tabu@err{\errmessage{(tabu) Internal impossible error! (\count@=\the\count@)}}
+%% The algorithms: compute the widths / stop or go on ---------------
+\def\tabu@arithnegcoef {%
+ \@tempdima \z@ \dimen@ \z@ \let\tabu@ \tabu@arith@negcoef \tabu@Xcoefs
+}% \tabu@arithnegcoef
+\def\tabu@arith@negcoef #1#2{%
+ \ifdim #2\p@>\z@ \advance\dimen@ #2\p@ % saturated by definition
+ \advance\@tempdima #2\tabucolX
+ \else
+ \ifdim -#2\tabucolX <\tabu@wd{#1}% c_i X < natural width <= \tabu@target-> saturated
+ \advance\dimen@ -#2\p@
+ \advance\@tempdima -#2\tabucolX
+ \else
+ \advance\@tempdima \tabu@wd{#1}% natural width <= c_i X => neutralised
+ \ifdim \tabu@wd{#1}<\tabu@target \else % neutralised
+ \advance\dimen@ -#2\p@ % saturated (natural width = tabu@target)
+ \fi
+ \fi
+ \fi
+}% \tabu@arith@negcoef
+\def\tabu@givespace #1#2{% here \tabu@DELTA < \z@
+ \ifdim \@tempdima=\z@
+ \tabu@wddef{#1}{\the\dimexpr -\tabu@DELTA*\p@/\tabu@Xsum}%
+ \else
+ \tabu@wddef{#1}{\the\dimexpr \tabu@hsize{#1}{#2}
+ *(\p@ -\tabu@DELTA*\p@/\@tempdima)/\p@\relax}%
+ \fi
+}% \tabu@givespace
+\def\tabu@arith {\advance\tabu@cnt \@ne
+ \ifnum \tabu@cnt=\@ne \tabu@message{\tabu@titles}\fi
+ \tabu@arithnegcoef
+ \@tempdimb \dimexpr \wd\tabu@box -\@tempdima \relax % <incompressible material>
+ \tabu@DELTA = \dimexpr \wd\tabu@box - \tabu@target \relax
+ \tabu@message{\tabu@message@arith}%
+ \ifdim \tabu@DELTA <\tabu@hfuzz
+ \ifdim \tabu@DELTA<\z@ % wd (tabu)<\tabu@target ?
+ \let\tabu@ \tabu@givespace \tabu@Xcoefs
+ \advance\@tempdima \@tempdimb \advance\@tempdima -\tabu@DELTA % for message
+ \else % already converged: nothing to do but nearly impossible...
+ \fi
+ \tabucolX \maxdimen
+ \tabu@measuringfalse
+ \else % need for narrower X columns
+ \tabucolX =\dimexpr (\@tempdima -\tabu@DELTA) *\p@/\tabu@Xsum \relax
+ \tabu@measuringtrue
+ \@whilesw \iftabu@measuring\fi {%
+ \advance\tabu@cnt \@ne
+ \tabu@arithnegcoef
+ \tabu@DELTA =\dimexpr \@tempdima+\@tempdimb -\tabu@target \relax % always < 0 here
+ \tabu@message{\tabu@header
+ \tabu@msgalign \tabucolX { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \@tempdima+\@tempdimb { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \tabu@target { }{ }{ }{ }{ }\@@
+ \tabu@msgalign@PT \dimen@ { }{}{}{}{}{}{}\@@
+ \ifdim -\tabu@DELTA<\tabu@hfuzz \tabu@spaces target ok\else
+ \tabu@msgalign \dimexpr -\tabu@DELTA *\p@/\dimen@ {}{}{}{}{}\@@
+ \fi}%
+ \ifdim -\tabu@DELTA<\tabu@hfuzz
+ \advance\@tempdima \@tempdimb % for message
+ \tabu@measuringfalse
+ \else
+ \advance\tabucolX \dimexpr -\tabu@DELTA *\p@/\dimen@ \relax
+ \fi
+ }%
+ \fi
+ \tabu@message{\tabu@message@reached}%
+ \edef\tabu@bufferX{\endgroup \tabu@cnt \the\tabu@cnt
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target}%
+}% \tabu@arith
+\def\tabu@spreadarith {%
+ \dimen@ \z@ \@tempdima \tabu@naturalXmax \let\tabu@ \tabu@spread@arith \tabu@Xcoefs
+ \edef\tabu@naturalXmin {\the\dimexpr\tabu@naturalXmin*\dimen@/\p@}%
+ \@tempdimc =\dimexpr \wd\tabu@box -\tabu@naturalXmax+\tabu@naturalXmin \relax
+ \iftabu@measuring
+ \tabu@target =\dimexpr \@tempdimc+\tabu@spreadtarget \relax
+ \edef\tabu@bufferX{\endgroup \tabucolX \the\tabucolX \tabu@target\the\tabu@target}%
+ \else
+ \tabu@message{\tabu@message@spreadarith}%
+ \ifdim \dimexpr \@tempdimc+\tabu@spreadtarget >\tabu@target
+ \tabu@message{(tabu) spread
+ \ifdim \@tempdimc>\tabu@target useless here: default target used%
+ \else too large: reduced to fit default target\fi.}%
+ \else
+ \tabu@target =\dimexpr \@tempdimc+\tabu@spreadtarget \relax
+ \tabu@message{(tabu) spread: New target set to \the\tabu@target^^J}%
+ \fi
+ \begingroup \let\tabu@wddef \@gobbletwo
+ \@tempdimb \@tempdima
+ \tabucolX@init
+ \tabu@arithnegcoef
+ \wd\tabu@box =\dimexpr \wd\tabu@box +\@tempdima-\@tempdimb \relax
+ \expandafter\endgroup \expandafter\tabucolX \the\tabucolX
+ \tabu@arith
+ \fi
+}% \tabu@spreadarith
+\def\tabu@spread@arith #1#2{%
+ \ifdim #2\p@>\z@ \advance\dimen@ #2\p@
+ \else \advance\@tempdima \tabu@wd{#1}\relax
+ \fi
+}% \tabu@spread@arith
+%% Reporting in the .log file ---------------------------------------
+\def\tabu@message@defaulttarget{%
+ \ifnum\tabu@nested=\z@^^J(tabu) Default target:
+ \ifx\tabudefaulttarget\linewidth \string\linewidth
+ \ifdim \tabu@thetarget=\linewidth \else
+ -\the\dimexpr\linewidth-\tabu@thetarget\fi =
+ \else\ifx\tabudefaulttarget\linegoal\string\linegoal=
+ \fi\fi
+ \else (tabu) Default target (nested): \fi
+ \the\tabu@target \on@line
+ \ifnum\tabu@nested=\z@ , page \the\c@page\fi}
+\def\tabu@message@target {^^J(tabu) Target specified:
+ \the\tabu@target \on@line, page \the\c@page}
+\def\tabu@message@arith {\tabu@header
+ \tabu@msgalign \tabucolX { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \wd\tabu@box { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \tabu@target { }{ }{ }{ }{ }\@@
+ \tabu@msgalign@PT \dimen@ { }{}{}{}{}{}{}\@@
+ \ifdim \tabu@DELTA<\tabu@hfuzz giving space\else
+ \tabu@msgalign \dimexpr (\@tempdima-\tabu@DELTA) *\p@/\tabu@Xsum -\tabucolX {}{}{}{}{}\@@
+ \fi
+}% \tabu@message@arith
+\def\tabu@message@spreadarith {\tabu@spreadheader
+ \tabu@msgalign \tabu@spreadtarget { }{ }{ }{ }{}\@@
+ \tabu@msgalign \wd\tabu@box { }{ }{ }{ }{}\@@
+ \tabu@msgalign -\tabu@naturalXmax { }{}{}{}{}\@@
+ \tabu@msgalign \tabu@naturalXmin { }{ }{ }{ }{}\@@
+ \tabu@msgalign \ifdim \dimexpr\@tempdimc>\tabu@target \tabu@target
+ \else \@tempdimc+\tabu@spreadtarget \fi
+ {}{}{}{}{}\@@}
+\def\tabu@message@negcoef #1#2{
+ \tabu@spaces\tabu@spaces\space * #1. X[\rem@pt#2]:
+ \space width = \tabu@wd {#1}
+ \expandafter\string\csname tabu@\the\tabu@nested.W\number#1\endcsname
+ \ifdim -\tabu@pt#2\tabucolX<\tabu@target
+ < \number-\rem@pt#2 X
+ = \the\dimexpr -\tabu@pt#2\tabucolX \relax
+ \else
+ <= \the\tabu@target\space < \number-\rem@pt#2 X\fi}
+\def\tabu@message@reached{\tabu@header
+ ******* Reached Target:
+ hfuzz = \tabu@hfuzz\on@line\space *******}
+\def\tabu@message@etime{\edef\tabu@stoptime{\the\pdfelapsedtime}%
+ \tabu@message{(tabu)\tabu@spaces Time elapsed during measure:
+ \the\numexpr(\tabu@stoptime-\tabu@starttime-32767)/65536\relax sec
+ \the\numexpr\numexpr(\tabu@stoptime-\tabu@starttime)
+ -\numexpr(\tabu@stoptime-\tabu@starttime-32767)/65536\relax*65536\relax
+ *1000/65536\relax ms \tabu@spaces(\the\tabu@cnt\space
+ cycle\ifnum\tabu@cnt>\@ne s\fi)^^J^^J}}
+\def\tabu@message@verticalsp {%
+ \ifdim \@tempdima>\tabu@ht
+ \ifdim \@tempdimb>\tabu@dp
+ \expandafter\expandafter\expandafter\string\tabu@ht =
+ \tabu@msgalign \@tempdima { }{ }{ }{ }{ }\@@
+ \expandafter\expandafter\expandafter\string\tabu@dp =
+ \tabu@msgalign \@tempdimb { }{ }{ }{ }{ }\@@^^J%
+ \else
+ \expandafter\expandafter\expandafter\string\tabu@ht =
+ \tabu@msgalign \@tempdima { }{ }{ }{ }{ }\@@^^J%
+ \fi
+ \else\ifdim \@tempdimb>\tabu@dp
+ \tabu@spaces\tabu@spaces\tabu@spaces
+ \expandafter\expandafter\expandafter\string\tabu@dp =
+ \tabu@msgalign \@tempdimb { }{ }{ }{ }{ }\@@^^J\fi
+ \fi
+}% \tabu@message@verticalsp
+\edef\tabu@spaces{\@spaces}
+\def\tabu@strippt{\expandafter\tabu@pt\the}
+{\@makeother\P \@makeother\T\lowercase{\gdef\tabu@pt #1PT{#1}}}
+\def\tabu@msgalign{\expandafter\tabu@msg@align\the\dimexpr}
+\def\tabu@msgalign@PT{\expandafter\tabu@msg@align\romannumeral-`\0\tabu@strippt}
+\def\do #1{%
+ \def\tabu@msg@align##1.##2##3##4##5##6##7##8##9\@@{%
+ \ifnum##1<10 #1 #1\else
+ \ifnum##1<100 #1 \else
+ \ifnum##1<\@m #1\fi\fi\fi
+ ##1.##2##3##4##5##6##7##8#1}%
+ \def\tabu@header{(tabu) \ifnum\tabu@cnt<10 #1\fi\the\tabu@cnt) }%
+ \def\tabu@titles{\ifnum \tabu@nested=\z@
+ (tabu) Try#1 #1 tabu X #1 #1 #1tabu Width #1 #1 Target
+ #1 #1 #1 Coefs #1 #1 #1 Update^^J\fi}%
+ \def\tabu@spreadheader{%
+ (tabu) Try#1 #1 Spread #1 #1 tabu Width #1 #1 #1 Nat. X #1 #1 #1 #1Nat. Min.
+ #1 New Target^^J%
+ (tabu) sprd}
+ \def\tabu@message@save {\begingroup
+ \def\x ####1{\tabu@msg@align ####1{ }{ }{ }{ }{}\@@}
+ \def\z ####1{\expandafter\x\expandafter{\romannumeral-`\0\tabu@strippt
+ \dimexpr####1\p@{ }{ }}}%
+ \let\color \relax \def\tabu@rulesstyle ####1####2{\detokenize{####1}}%
+ \let\CT@arc@ \relax \let\@preamble \@gobble
+ \let\tabu@savedpream \@firstofone
+ \let\tabu@savedparams \@firstofone
+ \def\tabu@target ####1\relax {(tabu) target #1 #1 #1 #1 #1 = \x{####1}^^J}%
+ \def\tabucolX ####1\relax {(tabu) X columns width#1 = \x{####1}^^J}%
+ \def\tabu@nbcols ####1\relax {(tabu) Number of columns: \z{####1}^^J}%
+ \def\tabu@aligndefault ####1{(tabu) Default alignment: #1 #1 ####1^^J}%
+ \def\col@sep ####1\relax {(tabu) column sep #1 #1 #1 = \x{####1}^^J}%
+ \def\arrayrulewidth ####1\relax{(tabu) arrayrulewidth #1 = \x{####1}}%
+ \def\doublerulesep ####1\relax { doublerulesep = \x{####1}^^J}%
+ \def\extratabsurround####1\relax{(tabu) extratabsurround = \x{####1}^^J}%
+ \def\extrarowheight ####1\relax{(tabu) extrarowheight #1 = \x{####1}}%
+ \def\extrarowdepth ####1\relax {extrarowdepth = \x{####1}^^J}%
+ \def\abovetabulinesep####1\relax{(tabu) abovetabulinesep=\x{####1} }%
+ \def\belowtabulinesep####1\relax{ belowtabulinesep=\x{####1}^^J}%
+ \def\arraystretch ####1{(tabu) arraystretch #1 #1 = \z{####1}^^J}%
+ \def\minrowclearance####1\relax{(tabu) minrowclearance #1 = \x{####1}^^J}%
+ \def\tabu@arc@L ####1{(tabu) taburulecolor #1 #1 = ####1^^J}%
+ \def\tabu@drsc@L ####1{(tabu) tabudoublerulecolor= ####1^^J}%
+ \def\tabu@evr@L ####1{(tabu) everyrow #1 #1 #1 #1 = \detokenize{####1}^^J}%
+ \def\tabu@ls@L ####1{(tabu) line style = \detokenize{####1}^^J}%
+ \def\NC@find ####1\@nil{(tabu) tabu preamble#1 #1 = \detokenize{####1}^^J}%
+ \def\tabu@wddef####1####2{(tabu) Natural width ####1 = \x{####2}^^J}%
+ \let\edef \@gobbletwo \let\def \@empty \let\let \@gobbletwo
+ \tabu@message{%
+ (tabu) \string\savetabu{\tabu@temp}: \on@line^^J%
+ \tabu@usetabu \@nil^^J}%
+ \endgroup}
+}\do{ }
+%% Measuring the natural width (varwidth) - store the results -------
+\def\tabu@startpboxmeasure #1{\bgroup % entering \vtop
+ \edef\tabu@temp{\expandafter\@secondoftwo \ifx\tabu@hsize #1\else\relax\fi}%
+ \ifodd 1\ifx \tabu@temp\@empty 0 \else % starts with \tabu@hsize ?
+ \iftabu@spread \else % if spread -> measure
+ \ifdim \tabu@temp\p@>\z@ 0 \fi\fi\fi% if coef>0 -> do not measure
+ \let\@startpbox \tabu@startpboxORI % restore immediately (nesting)
+ \tabu@measuringtrue % for the quick option...
+ \tabu@Xcol =\expandafter\@firstoftwo\ifx\tabu@hsize #1\fi
+ \ifdim \tabu@temp\p@>\z@ \ifdim \tabu@temp\tabucolX<\tabu@target
+ \tabu@target=\tabu@temp\tabucolX \fi\fi
+ \setbox\tabu@box \hbox \bgroup
+ \begin{varwidth}\tabu@target
+ \let\FV@ListProcessLine \tabu@FV@ListProcessLine % \hbox to natural width...
+ \narrowragged \arraybackslash \parfillskip \@flushglue
+ \ifdefined\pdfadjustspacing \pdfadjustspacing\z@ \fi
+ \bgroup \aftergroup\tabu@endpboxmeasure
+ \ifdefined \cellspacetoplimit \tabu@cellspacepatch \fi
+ \else \expandafter\@gobble
+ \tabu@startpboxquick{#1}% \@gobble \bgroup
+ \fi
+}% \tabu@startpboxmeasure
+\def\tabu@cellspacepatch{\def\bcolumn##1\@nil{}\let\ecolumn\@empty
+ \bgroup\color@begingroup}
+\def\tabu@endpboxmeasure {%
+ \@finalstrut \@arstrutbox
+ \end{varwidth}\egroup % <got my \tabu@box>
+ \ifdim \tabu@temp\p@ <\z@ % neg coef
+ \ifdim \tabu@wd\tabu@Xcol <\wd\tabu@box
+ \tabu@wddef\tabu@Xcol {\the\wd\tabu@box}%
+ \tabu@debug{\tabu@message@endpboxmeasure}%
+ \fi
+ \else % spread coef>0
+ \global\advance \tabu@naturalX \wd\tabu@box
+ \@tempdima =\dimexpr \wd\tabu@box *\p@/\dimexpr \tabu@temp\p@\relax \relax
+ \ifdim \tabu@naturalXmax <\tabu@naturalX
+ \xdef\tabu@naturalXmax {\the\tabu@naturalX}\fi
+ \ifdim \tabu@naturalXmin <\@tempdima
+ \xdef\tabu@naturalXmin {\the\@tempdima}\fi
+ \fi
+ \box\tabu@box \egroup % end of \vtop (measure) restore \tabu@target
+}% \tabu@endpboxmeasure
+\def\tabu@wddef #1{\expandafter\xdef
+ \csname tabu@\the\tabu@nested.W\number#1\endcsname}
+\def\tabu@wd #1{\csname tabu@\the\tabu@nested.W\number#1\endcsname}
+\def\tabu@message@endpboxmeasure{\tabu@spaces\tabu@spaces<-> % <-> save natural wd
+ \the\tabu@Xcol. X[\tabu@temp]:
+ target = \the\tabucolX \space
+ \expandafter\expandafter\expandafter\string\tabu@wd\tabu@Xcol
+ =\tabu@wd\tabu@Xcol
+}% \tabu@message@endpboxmeasure
+\def\tabu@startpboxquick {\bgroup
+ \let\@startpbox \tabu@startpboxORI % restore immediately
+ \let\tabu \tabu@quick % \begin is expanded before...
+ \expandafter\@gobble \@startpbox % gobbles \bgroup
+}% \tabu@startpboxquick
+\def\tabu@quick {\begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}\tabu@collectbody \tabu@endquick
+}% \tabu@quick
+\def\tabu@endquick {%
+ \ifodd 1\ifx\tabu@end@envir\tabu@endtabu \else
+ \ifx\tabu@end@envir\tabu@endtabus \else 0\fi\fi\relax
+ \endgroup
+ \else \let\endtabu \relax
+ \tabu@end@envir
+ \fi
+}% \tabu@quick
+\def\tabu@endtabu {\end{tabu}}
+\def\tabu@endtabus {\end{tabu*}}
+%% Measuring the heights and depths - store the results -------------
+\def\tabu@verticalmeasure{\everypar{}%
+ \ifnum \currentgrouptype>12 % 14=semi-simple, 15=math shift group
+ \setbox\tabu@box =\hbox\bgroup
+ \let\tabu@verticalspacing \tabu@verticalsp@lcr
+ \d@llarbegin % after \hbox ...
+ \else
+ \edef\tabu@temp{\ifnum\currentgrouptype=5\vtop
+ \else\ifnum\currentgrouptype=12\vcenter
+ \else\vbox\fi\fi}%
+ \setbox\tabu@box \hbox\bgroup$\tabu@temp \bgroup
+ \let\tabu@verticalspacing \tabu@verticalsp@pmb
+ \fi
+}% \tabu@verticalmeasure
+\def\tabu@verticalsp@lcr{%
+ \d@llarend \egroup % <got my \tabu@box>
+ \@tempdima \dimexpr \ht\tabu@box+\abovetabulinesep
+ \@tempdimb \dimexpr \dp\tabu@box+\belowtabulinesep \relax
+ \ifdim\tabustrutrule>\z@ \tabu@debug{\tabu@message@verticalsp}\fi
+ \ifdim \tabu@ht<\@tempdima \tabu@htdef{\the\@tempdima}\fi
+ \ifdim \tabu@dp<\@tempdimb \tabu@dpdef{\the\@tempdimb}\fi
+ \noindent\vrule height\@tempdima depth\@tempdimb
+}% \tabu@verticalsp@lcr
+\def\tabu@verticalsp@pmb{% inserts struts as needed
+ \par \expandafter\egroup
+ \expandafter$\expandafter
+ \egroup \expandafter
+ \@tempdimc \the\prevdepth
+ \@tempdima \dimexpr \ht\tabu@box+\abovetabulinesep
+ \@tempdimb \dimexpr \dp\tabu@box+\belowtabulinesep \relax
+ \ifdim\tabustrutrule>\z@ \tabu@debug{\tabu@message@verticalsp}\fi
+ \ifdim \tabu@ht<\@tempdima \tabu@htdef{\the\@tempdima}\fi
+ \ifdim \tabu@dp<\@tempdimb \tabu@dpdef{\the\@tempdimb}\fi
+ \let\@finalstrut \@gobble
+ \hrule height\@tempdima depth\@tempdimb width\hsize
+%% \box\tabu@box
+}% \tabu@verticalsp@pmb
+
+\def\tabu@verticalinit{%
+ \ifnum \c@taburow=\z@ \tabu@rearstrut \fi % after \tabu@reset !
+ \advance\c@taburow \@ne
+ \tabu@htdef{\the\ht\@arstrutbox}\tabu@dpdef{\the\dp\@arstrutbox}%
+ \advance\c@taburow \m@ne
+}% \tabu@verticalinit
+\def\tabu@htdef {\expandafter\xdef \csname tabu@\the\tabu@nested.H\the\c@taburow\endcsname}
+\def\tabu@ht {\csname tabu@\the\tabu@nested.H\the\c@taburow\endcsname}
+\def\tabu@dpdef {\expandafter\xdef \csname tabu@\the\tabu@nested.D\the\c@taburow\endcsname}
+\def\tabu@dp {\csname tabu@\the\tabu@nested.D\the\c@taburow\endcsname}
+\def\tabu@verticaldynamicadjustment {%
+ \advance\c@taburow \@ne
+ \extrarowheight \dimexpr\tabu@ht - \ht\strutbox
+ \extrarowdepth \dimexpr\tabu@dp - \dp\strutbox
+ \let\arraystretch \@empty
+ \advance\c@taburow \m@ne
+}% \tabu@verticaldynamicadjustment
+\def\tabuphantomline{\crcr \noalign{%
+ {\globaldefs \@ne
+ \setbox\@arstrutbox \box\voidb@x
+ \let\tabu@@celllalign \tabu@celllalign
+ \let\tabu@@cellralign \tabu@cellralign
+ \let\tabu@@cellleft \tabu@cellleft
+ \let\tabu@@cellright \tabu@cellright
+ \let\tabu@@thevline \tabu@thevline
+ \let\tabu@celllalign \@empty
+ \let\tabu@cellralign \@empty
+ \let\tabu@cellright \@empty
+ \let\tabu@cellleft \@empty
+ \let\tabu@thevline \relax}%
+ \edef\tabu@temp{\tabu@multispan \tabu@nbcols{\noindent &}}%
+ \toks@\expandafter{\tabu@temp \noindent\tabu@everyrowfalse \cr
+ \noalign{\tabu@rearstrut
+ {\globaldefs\@ne
+ \let\tabu@celllalign \tabu@@celllalign
+ \let\tabu@cellralign \tabu@@cellralign
+ \let\tabu@cellleft \tabu@@cellleft
+ \let\tabu@cellright \tabu@@cellright
+ \let\tabu@thevline \tabu@@thevline}}}%
+ \expandafter}\the\toks@
+}% \tabuphantomline
+%% \firsthline and \lasthline corrections ---------------------------
+\def\tabu@firstline {\tabu@hlineAZ \tabu@firsthlinecorrection {}}
+\def\tabu@firsthline{\tabu@hlineAZ \tabu@firsthlinecorrection \hline}
+\def\tabu@lastline {\tabu@hlineAZ \tabu@lasthlinecorrection {}}
+\def\tabu@lasthline {\tabu@hlineAZ \tabu@lasthlinecorrection \hline}
+\def\tabu@hline {% replaces \hline if no colortbl (see \AtBeginDocument)
+ \noalign{\ifnum0=`}\fi
+ {\CT@arc@\hrule height\arrayrulewidth}%
+ \futurelet \tabu@temp \tabu@xhline
+}% \tabu@hline
+\def\tabu@xhline{%
+ \ifx \tabu@temp \hline
+ {\ifx \CT@drsc@\relax \vskip
+ \else\ifx \CT@drsc@\@empty \vskip
+ \else \CT@drsc@\hrule height
+ \fi\fi
+ \doublerulesep}%
+ \fi
+ \ifnum0=`{\fi}%
+}% \tabu@xhline
+\def\tabu@hlineAZ #1#2{\noalign{\ifnum0=`}\fi \dimen@ \z@ \count@ \z@
+ \toks@{}\def\tabu@hlinecorrection{#1}\def\tabu@temp{#2}%
+ \tabu@hlineAZsurround
+}% \tabu@hlineAZ
+\newcommand*\tabu@hlineAZsurround[1][\extratabsurround]{%
+ \extratabsurround #1\let\tabucline \tabucline@scan
+ \let\hline \tabu@hlinescan \let\firsthline \hline
+ \let\cline \tabu@clinescan \let\lasthline \hline
+ \expandafter \futurelet \expandafter \tabu@temp
+ \expandafter \tabu@nexthlineAZ \tabu@temp
+}% \tabu@hlineAZsurround
+\def\tabu@hlinescan {\tabu@thick \arrayrulewidth \tabu@xhlineAZ \hline}
+\def\tabu@clinescan #1{\tabu@thick \arrayrulewidth \tabu@xhlineAZ {\cline{#1}}}
+\def\tabucline@scan{\@testopt \tabucline@sc@n {}}
+\def\tabucline@sc@n #1[#2]{\tabu@xhlineAZ {\tabucline[{#1}]{#2}}}
+\def\tabu@nexthlineAZ{%
+ \ifx \tabu@temp\hline \else
+ \ifx \tabu@temp\cline \else
+ \ifx \tabu@temp\tabucline \else
+ \tabu@hlinecorrection
+ \fi\fi\fi
+}% \tabu@nexthlineAZ
+\def\tabu@xhlineAZ #1{%
+ \toks@\expandafter{\the\toks@ #1}%
+ \@tempdimc \tabu@thick % The last line width
+ \ifcase\count@ \@tempdimb \tabu@thick % The first line width
+ \else \advance\dimen@ \dimexpr \tabu@thick+\doublerulesep \relax
+ \fi
+ \advance\count@ \@ne \futurelet \tabu@temp \tabu@nexthlineAZ
+}% \tabu@xhlineAZ
+\def\tabu@firsthlinecorrection{% \count@ = number of \hline -1
+ \@tempdima \dimexpr \ht\@arstrutbox+\dimen@
+ \edef\firsthline{% <local in \noalign>
+ \omit \hbox to\z@{\hss{\noexpand\tabu@DBG{yellow}\vrule
+ height \the\dimexpr\@tempdima+\extratabsurround
+ depth \dp\@arstrutbox
+ width \tabustrutrule}\hss}\cr
+ \noalign{\vskip -\the\dimexpr \@tempdima+\@tempdimb
+ +\dp\@arstrutbox \relax}%
+ \the\toks@
+ }\ifnum0=`{\fi
+ \expandafter}\firsthline % we are then !
+}% \tabu@firsthlinecorrection
+\def\tabu@lasthlinecorrection{%
+ \@tempdima \dimexpr \dp\@arstrutbox+\dimen@+\@tempdimb+\@tempdimc
+ \edef\lasthline{% <local in \noalign>
+ \the\toks@
+ \noalign{\vskip -\the\dimexpr\dimen@+\@tempdimb+\dp\@arstrutbox}%
+ \omit \hbox to\z@{\hss{\noexpand\tabu@DBG{yellow}\vrule
+ depth \the\dimexpr \dp\@arstrutbox+\@tempdimb+\dimen@
+ +\extratabsurround-\@tempdimc
+ height \z@
+ width \tabustrutrule}\hss}\cr
+ }\ifnum0=`{\fi
+ \expandafter}\lasthline % we are then !
+}% \tabu@lasthlinecorrection
+\def\tabu@LT@@hline{%
+ \ifx\LT@next\hline
+ \global\let\LT@next \@gobble
+ \ifx \CT@drsc@\relax
+ \gdef\CT@LT@sep{%
+ \noalign{\penalty-\@medpenalty\vskip\doublerulesep}}%
+ \else
+ \gdef\CT@LT@sep{%
+ \multispan\LT@cols{%
+ \CT@drsc@\leaders\hrule\@height\doublerulesep\hfill}\cr}%
+ \fi
+ \else
+ \global\let\LT@next\empty
+ \gdef\CT@LT@sep{%
+ \noalign{\penalty-\@lowpenalty\vskip-\arrayrulewidth}}%
+ \fi
+ \ifnum0=`{\fi}%
+ \multispan\LT@cols
+ {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
+ \CT@LT@sep
+ \multispan\LT@cols
+ {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
+ \noalign{\penalty\@M}%
+ \LT@next
+}% \tabu@LT@@hline
+%% Horizontal lines : \tabucline ------------------------------------
+\let\tabu@start \@tempcnta
+\let\tabu@stop \@tempcntb
+\newcommand*\tabucline{\noalign{\ifnum0=`}\fi \tabu@cline}
+\newcommand*\tabu@cline[2][]{\tabu@startstop{#2}%
+ \ifnum \tabu@stop<\z@ \toks@{}%
+ \else \tabu@clinearg{#1}\tabu@thestyle
+ \edef\tabucline{\toks@{%
+ \ifnum \tabu@start>\z@ \omit
+ \tabu@multispan\tabu@start {\span\omit}&\fi
+ \omit \tabu@multispan\tabu@stop {\span\omit}%
+ \tabu@thehline\cr
+ }}\tabucline
+ \tabu@tracinglines{(tabu:tabucline) Style: #1^^J\the\toks@^^J^^J}%
+ \fi
+ \futurelet \tabu@temp \tabu@xcline
+}% \tabu@cline
+\def\tabu@clinearg #1{%
+ \ifx\\#1\\\let\tabu@thestyle \tabu@ls@
+ \else \@defaultunits \expandafter\let\expandafter\@tempa
+ \romannumeral-`\0#1\relax \@nnil
+ \ifx \hbox\@tempa \tabu@clinebox{#1}%
+ \else\ifx \box\@tempa \tabu@clinebox{#1}%
+ \else\ifx \vbox\@tempa \tabu@clinebox{#1}%
+ \else\ifx \vtop\@tempa \tabu@clinebox{#1}%
+ \else\ifx \copy\@tempa \tabu@clinebox{#1}%
+ \else\ifx \leaders\@tempa \tabu@clineleads{#1}%
+ \else\ifx \cleaders\@tempa \tabu@clineleads{#1}%
+ \else\ifx \xleaders\@tempa \tabu@clineleads{#1}%
+ \else\tabu@getline {#1}%
+ \fi\fi\fi\fi\fi\fi\fi\fi
+ \fi
+}% \tabu@clinearg
+\def\tabu@clinebox #1{\tabu@clineleads{\xleaders#1\hss}}
+\def\tabu@clineleads #1{%
+ \let\tabu@thestyle \relax \let\tabu@leaders \@undefined
+ \gdef\tabu@thehrule{#1}}
+\def\tabu@thehline{\begingroup
+ \ifdefined\tabu@leaders
+ \noexpand\tabu@thehleaders
+ \else \noexpand\tabu@thehrule
+ \fi \endgroup
+}% \tabu@thehline
+\def\tabu@xcline{%
+ \ifx \tabu@temp\tabucline
+ \toks@\expandafter{\the\toks@ \noalign
+ {\ifx\CT@drsc@\relax \vskip
+ \else \CT@drsc@\hrule height
+ \fi
+ \doublerulesep}}%
+ \fi
+ \tabu@docline
+}% \tabu@xcline
+\def\tabu@docline {\ifnum0=`{\fi \expandafter}\the\toks@}
+\def\tabu@docline@evr {\xdef\tabu@doclineafter{\the\toks@}%
+ \ifnum0=`{\fi}\aftergroup\tabu@doclineafter}
+\def\tabu@multispan #1#2{%
+ \ifnum\numexpr#1>\@ne #2\expandafter\tabu@multispan
+ \else \expandafter\@gobbletwo
+ \fi {#1-1}{#2}%
+}% \tabu@multispan
+\def\tabu@startstop #1{\tabu@start@stop #1\relax 1-\tabu@nbcols \@nnil}
+\def\tabu@start@stop #1-#2\@nnil{%
+ \@defaultunits \tabu@start\number 0#1\relax \@nnil
+ \@defaultunits \tabu@stop \number 0#2\relax \@nnil
+ \tabu@stop \ifnum \tabu@start>\tabu@nbcols \m@ne
+ \else\ifnum \tabu@stop=\z@ \tabu@nbcols
+ \else\ifnum \tabu@stop>\tabu@nbcols \tabu@nbcols
+ \else \tabu@stop
+ \fi\fi\fi
+ \advance\tabu@start \m@ne
+ \ifnum \tabu@start>\z@ \advance\tabu@stop -\tabu@start \fi
+}% \tabu@start@stop
+%% Numbers: siunitx S columns (and \tabudecimal) -------------------
+\def\tabu@tabudecimal #1{%
+ \def\tabu@decimal{#1}\@temptokena{}%
+ \let\tabu@getdecimal@ \tabu@getdecimal@ignorespaces
+ \tabu@scandecimal
+}% \tabu@tabudecimal
+\def\tabu@scandecimal{\futurelet \tabu@temp \tabu@getdecimal@}
+\def\tabu@skipdecimal#1{#1\tabu@scandecimal}
+\def\tabu@getdecimal@ignorespaces{%
+ \ifcase 0\ifx\tabu@temp\ignorespaces\else
+ \ifx\tabu@temp\@sptoken1\else
+ 2\fi\fi\relax
+ \let\tabu@getdecimal@ \tabu@getdecimal
+ \expandafter\tabu@skipdecimal
+ \or \expandafter\tabu@gobblespace\expandafter\tabu@scandecimal
+ \else \expandafter\tabu@skipdecimal
+ \fi
+}% \tabu@getdecimal@ignorespaces
+\def\tabu@get@decimal#1{\@temptokena\expandafter{\the\@temptokena #1}%
+ \tabu@scandecimal}
+\def\do#1{%
+ \def\tabu@get@decimalspace#1{%
+ \@temptokena\expandafter{\the\@temptokena #1}\tabu@scandecimal}%
+}\do{ }
+\let\tabu@@tabudecimal \tabu@tabudecimal
+\def\tabu@getdecimal{%
+ \ifcase 0\ifx 0\tabu@temp\else
+ \ifx 1\tabu@temp\else
+ \ifx 2\tabu@temp\else
+ \ifx 3\tabu@temp\else
+ \ifx 4\tabu@temp\else
+ \ifx 5\tabu@temp\else
+ \ifx 6\tabu@temp\else
+ \ifx 7\tabu@temp\else
+ \ifx 8\tabu@temp\else
+ \ifx 9\tabu@temp\else
+ \ifx .\tabu@temp\else
+ \ifx ,\tabu@temp\else
+ \ifx -\tabu@temp\else
+ \ifx +\tabu@temp\else
+ \ifx e\tabu@temp\else
+ \ifx E\tabu@temp\else
+ \ifx\tabu@cellleft\tabu@temp1\else
+ \ifx\ignorespaces\tabu@temp1\else
+ \ifx\@sptoken\tabu@temp2\else
+ 3\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\relax
+ \expandafter\tabu@get@decimal
+ \or \expandafter\tabu@skipdecimal
+ \or \expandafter\tabu@get@decimalspace
+ \else\expandafter\tabu@printdecimal
+ \fi
+}% \tabu@getdecimal
+\def\tabu@printdecimal{%
+ \edef\tabu@temp{\the\@temptokena}%
+ \ifx\tabu@temp\@empty\else
+ \ifx\tabu@temp\space\else
+ \expandafter\tabu@decimal\expandafter{\the\@temptokena}%
+ \fi\fi
+}% \tabu@printdecimal
+%% Verbatim inside X columns ----------------------------------------
+\def\tabu@verbatim{%
+ \let\verb \tabu@verb
+ \let\FV@DefineCheckEnd \tabu@FV@DefineCheckEnd
+}% \tabu@verbatim
+\let\tabu@ltx@verb \verb
+\def\tabu@verb{\@ifstar {\tabu@ltx@verb*} \tabu@ltx@verb}
+\def\tabu@fancyvrb {%
+ \def\tabu@FV@DefineCheckEnd ##1{%
+ \def\tabu@FV@DefineCheckEnd{%
+ ##1% <original definition (if fancyvrb is loaded)>
+ \let\FV@CheckEnd \tabu@FV@CheckEnd
+ \let\FV@@CheckEnd \tabu@FV@@CheckEnd
+ \let\FV@@@CheckEnd \tabu@FV@@@CheckEnd
+ \edef\FV@EndScanning{%
+ \def\noexpand\next{\noexpand\end{\FV@EnvironName}}%
+ \global\let\noexpand\FV@EnvironName\relax
+ \noexpand\next}%
+ \xdef\FV@EnvironName{\detokenize\expandafter{\FV@EnvironName}}}%
+ }\expandafter\tabu@FV@DefineCheckEnd\expandafter{\FV@DefineCheckEnd}
+}% \tabu@fancyvrb
+\def\tabu@FV@CheckEnd #1{\expandafter\FV@@CheckEnd \detokenize{#1\end{}}\@nil}
+\edef\tabu@FV@@@CheckEnd {\detokenize{\end{}}}
+\begingroup
+\catcode`\[1 \catcode`\]2
+\@makeother\{ \@makeother\}
+ \edef\x[\endgroup
+ \def\noexpand\tabu@FV@@CheckEnd ##1\detokenize[\end{]##2\detokenize[}]##3%
+ ]\x \@nil{\def\@tempa{#2}\def\@tempb{#3}}
+\def\tabu@FV@ListProcessLine #1{%
+ \hbox {%to \hsize{%
+ \kern\leftmargin
+ \hbox {%to \linewidth{%
+ \FV@LeftListNumber
+ \FV@LeftListFrame
+ \FancyVerbFormatLine{#1}\hss
+%% DG/SR modification begin - Jan. 28, 1998 (for numbers=right add-on)
+%% \FV@RightListFrame}%
+ \FV@RightListFrame
+ \FV@RightListNumber}%
+%% DG/SR modification end
+ \hss}}
+%% \savetabu --------------------------------------------------------
+\newcommand*\savetabu[1]{\noalign{%
+ \tabu@sanitizearg{#1}\tabu@temp
+ \ifx \tabu@temp\@empty \tabu@savewarn{}{The tabu will not be saved}\else
+ \@ifundefined{tabu@saved@\tabu@temp}{}{\tabu@savewarn{#1}{Overwritting}}%
+ \ifdefined\tabu@restored \expandafter\let
+ \csname tabu@saved@\tabu@temp \endcsname \tabu@restored
+ \else {\tabu@save}%
+ \fi
+ \fi}%
+}% \savetabu
+\def\tabu@save {%
+ \toks0\expandafter{\tabu@saved@}%
+ \iftabu@negcoef
+ \let\tabu@wddef \relax \let\tabu@ \tabu@savewd \edef\tabu@savewd{\tabu@Xcoefs}%
+ \toks0\expandafter{\the\toks\expandafter0\tabu@savewd}\fi
+ \toks1\expandafter{\tabu@savedpream}%
+ \toks2\expandafter{\tabu@savedpreamble}%
+ \let\@preamble \relax
+ \let\tabu@savedpream \relax \let\tabu@savedparams \relax
+ \edef\tabu@preamble{%
+ \def\noexpand\tabu@aligndefault{\tabu@align}%
+ \def\tabu@savedparams {\noexpand\the\toks0}%
+ \def\tabu@savedpream {\noexpand\the\toks1}}%
+ \edef\tabu@usetabu{%
+ \def\@preamble {\noexpand\the\toks2}%
+ \tabu@target \the\tabu@target \relax
+ \tabucolX \the\tabucolX \relax
+ \tabu@nbcols \the\tabu@nbcols \relax
+ \def\noexpand\tabu@aligndefault{\tabu@align}%
+ \def\tabu@savedparams {\noexpand\the\toks0}%
+ \def\tabu@savedpream {\noexpand\the\toks1}}%
+ \let\tabu@aligndefault \relax \let\@sharp \relax
+ \edef\@tempa{\noexpand\tabu@s@ved
+ {\tabu@usetabu}
+ {\tabu@preamble}
+ {\the\toks1}}\@tempa
+ \tabu@message@save
+}% \tabu@save
+\long\def\tabu@s@ved #1#2#3{%
+ \def\tabu@usetabu{#1}% <for \tabu@message@save>
+ \expandafter\gdef\csname tabu@saved@\tabu@temp\endcsname ##1{%
+ \ifodd ##1% \usetabu
+ \tabu@measuringfalse \tabu@spreadfalse % Just in case...
+ \gdef\tabu@usetabu {%
+ \ifdim \tabu@target>\z@ \tabu@warn@usetabu \fi
+ \global\let\tabu@usetabu \@undefined
+ \def\@halignto {to\tabu@target}%
+ #1%
+ \ifx \tabu@align\tabu@aligndefault@text
+ \ifnum \tabu@nested=\z@
+ \let\tabu@align \tabu@aligndefault \fi\fi}%
+ \else % \preamble
+ \gdef\tabu@preamble {%
+ \global\let\tabu@preamble \@undefined
+ #2%
+ \ifx \tabu@align\tabu@aligndefault@text
+ \ifnum \tabu@nested=\z@
+ \let\tabu@align \tabu@aligndefault \fi\fi}%
+ \fi
+ #3}%
+}% \tabu@s@ved
+\def\tabu@aligndefault@text {\tabu@aligndefault}%
+\def\tabu@warn@usetabu {\PackageWarning{tabu}
+ {Specifying a target with \string\usetabu\space is useless
+ \MessageBreak The target cannot be changed!}}
+\def\tabu@savewd #1#2{\ifdim #2\p@<\z@ \tabu@wddef{#1}{\tabu@wd{#1}}\fi}
+\def\tabu@savewarn#1#2{\PackageInfo{tabu}
+ {User-name `#1' already used for \string\savetabu
+ \MessageBreak #2}}%
+\def\tabu@saveerr#1{\PackageError{tabu}
+ {User-name `#1' is unknown for \string\usetabu
+ \MessageBreak I cannot restore an unknown preamble!}\@ehd}
+%% \rowfont ---------------------------------------------------------
+\newskip \tabu@cellskip
+\def\tabu@rowfont{\ifdim \baselineskip=\z@\noalign\fi
+ {\ifnum0=`}\fi \tabu@row@font}
+\newcommand*\tabu@row@font[2][]{%
+ \ifnum7=\currentgrouptype
+ \global\let\tabu@@cellleft \tabu@cellleft
+ \global\let\tabu@@cellright \tabu@cellright
+ \global\let\tabu@@celllalign \tabu@celllalign
+ \global\let\tabu@@cellralign \tabu@cellralign
+ \global\let\tabu@@rowfontreset\tabu@rowfontreset
+ \fi
+ \global\let\tabu@rowfontreset \tabu@rowfont@reset
+ \expandafter\gdef\expandafter\tabu@cellleft\expandafter{\tabu@cellleft #2}%
+ \ifcsname tabu@cell@#1\endcsname % row alignment
+ \csname tabu@cell@#1\endcsname \fi
+ \ifnum0=`{\fi}% end of group / noalign group
+}% \rowfont
+\def\tabu@ifcolorleavevmode #1{\let\color \tabu@leavevmodecolor #1\let\color\tabu@color}%
+\def\tabu@rowfont@reset{%
+ \global\let\tabu@rowfontreset \tabu@@rowfontreset
+ \global\let\tabu@cellleft \tabu@@cellleft
+ \global\let\tabu@cellright \tabu@@cellright
+ \global\let\tabu@cellfont \@empty
+ \global\let\tabu@celllalign \tabu@@celllalign
+ \global\let\tabu@cellralign \tabu@@cellralign
+}% \tabu@@rowfontreset
+\let\tabu@rowfontreset \@empty % overwritten \AtBeginDocument if colortbl
+%% \tabu@prepnext@tok -----------------------------------------------
+\newif \iftabu@cellright
+\def\tabu@prepnext@tok{%
+ \ifnum \count@<\z@ % <first initialisation>
+ \@tempcnta \@M % <not initialized by array.sty>
+ \tabu@nbcols\z@
+ \let\tabu@fornoopORI \@fornoop
+ \tabu@cellrightfalse
+ \else
+ \ifcase \numexpr \count@-\@tempcnta \relax % (case 0): prev. token is left
+ \advance \tabu@nbcols \@ne
+ \iftabu@cellright % before-previous token is right and is finished
+ \tabu@cellrightfalse % <only once>
+ \tabu@righttok
+ \fi
+ \tabu@lefttok
+ \or % (case 1) previous token is right
+ \tabu@cellrighttrue \let\@fornoop \tabu@lastnoop
+ \else % special column: do not change the token
+ \iftabu@cellright % before-previous token is right
+ \tabu@cellrightfalse
+ \tabu@righttok
+ \fi
+ \fi % \ifcase
+ \fi
+ \tabu@prepnext@tokORI
+}% \tabu@prepnext@tok
+\long\def\tabu@lastnoop#1\@@#2#3{\tabu@lastn@@p #2\@nextchar \in@\in@@}
+\def\tabu@lastn@@p #1\@nextchar #2#3\in@@{%
+ \ifx \in@#2\else
+ \let\@fornoop \tabu@fornoopORI
+ \xdef\tabu@mkpreambuffer{\tabu@nbcols\the\tabu@nbcols \tabu@mkpreambuffer}%
+ \toks0\expandafter{\expandafter\tabu@everyrowtrue \the\toks0}%
+ \expandafter\prepnext@tok
+ \fi
+}% \tabu@lastnoop
+\def\tabu@righttok{%
+ \advance \count@ \m@ne
+ \toks\count@\expandafter {\the\toks\count@ \tabu@cellright \tabu@cellralign}%
+ \advance \count@ \@ne
+}% \tabu@righttok
+\def\tabu@lefttok{\toks\count@\expandafter{\expandafter\tabu@celllalign
+ \the\toks\count@ \tabu@cellleft}% after because of $
+}% \tabu@lefttok
+%% Neutralisation of glues ------------------------------------------
+\let\tabu@cellleft \@empty
+\let\tabu@cellright \@empty
+\tabu@celllalign@def{\tabu@cellleft}%
+\let\tabu@cellralign \@empty
+\def\tabu@cell@align #1#2#3{%
+ \let\tabu@maybesiunitx \toks@ \tabu@celllalign
+ \global \expandafter \tabu@celllalign@def \expandafter {\the\toks@ #1}%
+ \toks@\expandafter{\tabu@cellralign #2}%
+ \xdef\tabu@cellralign{\the\toks@}%
+ \toks@\expandafter{\tabu@cellleft #3}%
+ \xdef\tabu@cellleft{\the\toks@}%
+}% \tabu@cell@align
+\def\tabu@cell@l{% force alignment to left
+ \tabu@cell@align
+ {\tabu@removehfil \raggedright \tabu@cellleft}% left
+ {\tabu@flush1\tabu@ignorehfil}% right
+ \raggedright
+}% \tabu@cell@l
+\def\tabu@cell@c{% force alignment to center
+ \tabu@cell@align
+ {\tabu@removehfil \centering \tabu@flush{.5}\tabu@cellleft}
+ {\tabu@flush{.5}\tabu@ignorehfil}
+ \centering
+}% \tabu@cell@c
+\def\tabu@cell@r{% force alignment to right
+ \tabu@cell@align
+ {\tabu@removehfil \raggedleft \tabu@flush1\tabu@cellleft}
+ \tabu@ignorehfil
+ \raggedleft
+}% \tabu@cell@r
+\def\tabu@cell@j{% force justification (for p, m, b columns)
+ \tabu@cell@align
+ {\tabu@justify\tabu@cellleft}
+ {}
+ \tabu@justify
+}% \tabu@cell@j
+\def\tabu@justify{%
+ \leftskip\z@skip \@rightskip\leftskip \rightskip\@rightskip
+ \parfillskip\@flushglue
+}% \tabu@justify
+%% ragged2e settings
+\def\tabu@cell@L{% force alignment to left (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \RaggedRight \tabu@cellleft}
+ {\tabu@flush 1\tabu@ignorehfil}
+ \RaggedRight
+}% \tabu@cell@L
+\def\tabu@cell@C{% force alignment to center (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \Centering \tabu@flush{.5}\tabu@cellleft}
+ {\tabu@flush{.5}\tabu@ignorehfil}
+ \Centering
+}% \tabu@cell@C
+\def\tabu@cell@R{% force alignment to right (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \RaggedLeft \tabu@flush 1\tabu@cellleft}
+ \tabu@ignorehfil
+ \RaggedLeft
+}% \tabu@cell@R
+\def\tabu@cell@J{% force justification (ragged2e)
+ \tabu@cell@align
+ {\justifying \tabu@cellleft}
+ {}
+ \justifying
+}% \tabu@cell@J
+\def\tabu@flush#1{%
+ \iftabu@colortbl % colortbl uses \hfill rather than \hfil
+ \hskip \ifnum13<\currentgrouptype \stretch{#1}%
+ \else \ifdim#1pt<\p@ \tabu@cellskip
+ \else \stretch{#1}
+ \fi\fi \relax
+ \else % array.sty
+ \ifnum 13<\currentgrouptype
+ \hfil \hskip1sp \relax \fi
+ \fi
+}% \tabu@flush
+\let\tabu@hfil \hfil
+\let\tabu@hfill \hfill
+\let\tabu@hskip \hskip
+\def\tabu@removehfil{%
+ \iftabu@colortbl
+ \unkern \tabu@cellskip =\lastskip
+ \ifnum\gluestretchorder\tabu@cellskip =\tw@ \hskip-\tabu@cellskip
+ \else \tabu@cellskip \z@skip
+ \fi
+ \else
+ \ifdim\lastskip=1sp\unskip\fi
+ \ifnum\gluestretchorder\lastskip =\@ne
+ \hfilneg % \hfilneg for array.sty but not for colortbl...
+ \fi
+ \fi
+}% \tabu@removehfil
+\def\tabu@ignorehfil{\aftergroup \tabu@nohfil}
+\def\tabu@nohfil{% \hfil -> do nothing + restore original \hfil
+ \def\hfil{\let\hfil \tabu@hfil}% local to (alignment template) group
+}% \tabu@nohfil
+\def\tabu@colortblalignments {% if colortbl
+ \def\tabu@nohfil{%
+ \def\hfil {\let\hfil \tabu@hfil}% local to (alignment template) group
+ \def\hfill {\let\hfill \tabu@hfill}% (colortbl uses \hfill) pfff...
+ \def\hskip ####1\relax{\let\hskip \tabu@hskip}}% local
+}% \tabu@colortblalignments
+%% Taking care of footnotes and hyperfootnotes ----------------------
+\long\def\tabu@footnotetext #1{%
+ \edef\@tempa{\the\tabu@footnotes
+ \noexpand\footnotetext [\the\csname c@\@mpfn\endcsname]}%
+ \global\tabu@footnotes\expandafter{\@tempa {#1}}}%
+\long\def\tabu@xfootnotetext [#1]#2{%
+ \global\tabu@footnotes\expandafter{\the\tabu@footnotes
+ \footnotetext [{#1}]{#2}}}
+\let\tabu@xfootnote \@xfootnote
+\long\def\tabu@Hy@ftntext{\tabu@Hy@ftntxt {\the \c@footnote }}
+\long\def\tabu@Hy@xfootnote [#1]{%
+ \begingroup
+ \value\@mpfn #1\relax
+ \protected@xdef \@thefnmark {\thempfn}%
+ \endgroup
+ \@footnotemark \tabu@Hy@ftntxt {#1}%
+}% \tabu@Hy@xfootnote
+\long\def\tabu@Hy@ftntxt #1#2{%
+ \edef\@tempa{%
+ \the\tabu@footnotes
+ \begingroup
+ \value\@mpfn #1\relax
+ \noexpand\protected@xdef\noexpand\@thefnmark {\noexpand\thempfn}%
+ \expandafter \noexpand \expandafter
+ \tabu@Hy@footnotetext \expandafter{\Hy@footnote@currentHref}%
+ }%
+ \global\tabu@footnotes\expandafter{\@tempa {#2}%
+ \endgroup}%
+}% \tabu@Hy@ftntxt
+\long\def\tabu@Hy@footnotetext #1#2{%
+ \H@@footnotetext{%
+ \ifHy@nesting
+ \hyper@@anchor {#1}{#2}%
+ \else
+ \Hy@raisedlink{%
+ \hyper@@anchor {#1}{\relax}%
+ }%
+ \def\@currentHref {#1}%
+ \let\@currentlabelname \@empty
+ #2%
+ \fi
+ }%
+}% \tabu@Hy@footnotetext
+%% No need for \arraybackslash ! ------------------------------------
+\def\tabu@latextwoe {%
+\def\tabu@temp##1##2##3{{\toks@\expandafter{##2##3}\xdef##1{\the\toks@}}}
+\tabu@temp \tabu@centering \centering \arraybackslash
+\tabu@temp \tabu@raggedleft \raggedleft \arraybackslash
+\tabu@temp \tabu@raggedright \raggedright \arraybackslash
+}% \tabu@latextwoe
+\def\tabu@raggedtwoe {%
+\def\tabu@temp ##1##2##3{{\toks@\expandafter{##2##3}\xdef##1{\the\toks@}}}
+\tabu@temp \tabu@Centering \Centering \arraybackslash
+\tabu@temp \tabu@RaggedLeft \RaggedLeft \arraybackslash
+\tabu@temp \tabu@RaggedRight \RaggedRight \arraybackslash
+\tabu@temp \tabu@justifying \justifying \arraybackslash
+}% \tabu@raggedtwoe
+\def\tabu@normalcrbackslash{\let\\\@normalcr}
+\def\tabu@trivlist{\expandafter\def\expandafter\@trivlist\expandafter{%
+ \expandafter\tabu@normalcrbackslash \@trivlist}}
+%% Utilities: \fbox \fcolorbox and \tabudecimal -------------------
+\def\tabu@fbox {\leavevmode\afterassignment\tabu@beginfbox \setbox\@tempboxa\hbox}
+\def\tabu@beginfbox {\bgroup \kern\fboxsep
+ \bgroup\aftergroup\tabu@endfbox}
+\def\tabu@endfbox {\kern\fboxsep\egroup\egroup
+ \@frameb@x\relax}
+\def\tabu@color@b@x #1#2{\leavevmode \bgroup
+ \def\tabu@docolor@b@x{#1{#2\color@block{\wd\z@}{\ht\z@}{\dp\z@}\box\z@}}%
+ \afterassignment\tabu@begincolor@b@x \setbox\z@ \hbox
+}% \tabu@color@b@x
+\def\tabu@begincolor@b@x {\kern\fboxsep \bgroup
+ \aftergroup\tabu@endcolor@b@x \set@color}
+\def\tabu@endcolor@b@x {\kern\fboxsep \egroup
+ \dimen@\ht\z@ \advance\dimen@ \fboxsep \ht\z@ \dimen@
+ \dimen@\dp\z@ \advance\dimen@ \fboxsep \dp\z@ \dimen@
+ \tabu@docolor@b@x \egroup
+}% \tabu@endcolor@b@x
+%% Corrections (arydshln, delarray, colortbl) -----------------------
+\def\tabu@fix@arrayright {%% \@arrayright is missing from \endarray
+ \iftabu@colortbl
+ \ifdefined\adl@array % <colortbl + arydshln>
+ \def\tabu@endarray{%
+ \adl@endarray \egroup \adl@arrayrestore \CT@end \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}}% <FC>
+ \else % <colortbl / no arydshln>
+ \def\tabu@endarray{%
+ \crcr \egroup \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}\CT@end}%
+ \fi
+ \else
+ \ifdefined\adl@array % <arydshln / no colortbl>
+ \def\tabu@endarray{%
+ \adl@endarray \egroup \adl@arrayrestore \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}}% <FC>
+ \else % <no arydshln / no colotbl + \@arrayright missing>
+ \PackageWarning{tabu}
+ {\string\@arrayright\space is missing from the
+ \MessageBreak definition of \string\endarray.
+ \MessageBreak Comptability with delarray.sty is broken.}%
+ \fi\fi
+}% \tabu@fix@arrayright
+\def\tabu@adl@xarraydashrule #1#2#3{%
+ \ifnum\@lastchclass=\adl@class@start\else
+ \ifnum\@lastchclass=\@ne\else
+ \ifnum\@lastchclass=5 \else % <FC> @-arg (class 5) and !-arg (class 1)
+ \adl@leftrulefalse \fi\fi % must be treated the same
+ \fi
+ \ifadl@zwvrule\else \ifadl@inactive\else
+ \@addtopreamble{\vrule\@width\arrayrulewidth
+ \@height\z@ \@depth\z@}\fi \fi
+ \ifadl@leftrule
+ \@addtopreamble{\adl@vlineL{\CT@arc@}{\adl@dashgapcolor}%
+ {\number#1}#3}%
+ \else \@addtopreamble{\adl@vlineR{\CT@arc@}{\adl@dashgapcolor}%
+ {\number#2}#3}
+ \fi
+}% \tabu@adl@xarraydashrule
+\def\tabu@adl@act@endpbox {%
+ \unskip \ifhmode \nobreak \fi \@finalstrut \@arstrutbox
+ \egroup \egroup
+ \adl@colhtdp \box\adl@box \hfil
+}% \tabu@adl@act@endpbox
+\def\tabu@adl@fix {%
+ \let\adl@xarraydashrule \tabu@adl@xarraydashrule % <fix> arydshln
+ \let\adl@act@endpbox \tabu@adl@act@endpbox % <fix> arydshln
+ \let\adl@act@@endpbox \tabu@adl@act@endpbox % <fix> arydshln
+ \let\@preamerror \@preamerr % <fix> arydshln
+}% \tabu@adl@fix
+%% Correction for longtable' \@startbox definition ------------------
+%% => \everypar is ``missing'' : TeX should be in vertical mode
+\def\tabu@LT@startpbox #1{%
+ \bgroup
+ \let\@footnotetext\LT@p@ftntext
+ \setlength\hsize{#1}%
+ \@arrayparboxrestore
+ \everypar{%
+ \vrule \@height \ht\@arstrutbox \@width \z@
+ \everypar{}}%
+}% \tabu@LT@startpbox
+%% \tracingtabu and the package options ------------------
+\DeclareOption{delarray}{\AtEndOfPackage{\RequirePackage{delarray}}}
+\DeclareOption{linegoal}{%
+ \AtEndOfPackage{%
+ \RequirePackage{linegoal}[2010/12/07]%
+ \let\tabudefaulttarget \linegoal% \linegoal is \linewidth if not pdfTeX
+}}
+\DeclareOption{scantokens}{\tabuscantokenstrue}
+\DeclareOption{debugshow}{\AtEndOfPackage{\tracingtabu=\tw@}}
+\def\tracingtabu {\begingroup\@ifnextchar=%
+ {\afterassignment\tabu@tracing\count@}
+ {\afterassignment\tabu@tracing\count@1\relax}}
+\def\tabu@tracing{\expandafter\endgroup
+ \expandafter\tabu@tr@cing \the\count@ \relax
+}% \tabu@tracing
+\def\tabu@tr@cing #1\relax {%
+ \ifnum#1>\thr@@ \let\tabu@tracinglines\message
+ \else \let\tabu@tracinglines\@gobble
+ \fi
+ \ifnum#1>\tw@ \let\tabu@DBG \tabu@@DBG
+ \def\tabu@mkarstrut {\tabu@DBG@arstrut}%
+ \tabustrutrule 1.5\p@
+ \else \let\tabu@DBG \@gobble
+ \def\tabu@mkarstrut {\tabu@arstrut}%
+ \tabustrutrule \z@
+ \fi
+ \ifnum#1>\@ne \let\tabu@debug \message
+ \else \let\tabu@debug \@gobble
+ \fi
+ \ifnum#1>\z@
+ \let\tabu@message \message
+ \let\tabu@tracing@save \tabu@message@save
+ \let\tabu@starttimer \tabu@pdftimer
+ \else
+ \let\tabu@message \@gobble
+ \let\tabu@tracing@save \@gobble
+ \let\tabu@starttimer \relax
+ \fi
+}% \tabu@tr@cing
+%% Setup \AtBeginDocument
+\AtBeginDocument{\tabu@AtBeginDocument}
+\def\tabu@AtBeginDocument{\let\tabu@AtBeginDocument \@undefined
+ \ifdefined\arrayrulecolor \tabu@colortbltrue % <colortbl>
+ \tabu@colortblalignments % different glues are used
+ \else \tabu@colortblfalse \fi
+ \ifdefined\CT@arc@ \else \let\CT@arc@ \relax \fi
+ \ifdefined\CT@drsc@\else \let\CT@drsc@ \relax \fi
+ \let\tabu@arc@L \CT@arc@ \let\tabu@drsc@L \CT@drsc@
+ \ifodd 1\ifcsname siunitx_table_collect_begin:Nn\endcsname % <siunitx: ok>
+ \expandafter\ifx
+ \csname siunitx_table_collect_begin:Nn\endcsname\relax 0\fi\fi\relax
+ \tabu@siunitxtrue
+ \else \let\tabu@maybesiunitx \@firstofone % <not siunitx: setup>
+ \let\tabu@siunitx \tabu@nosiunitx
+ \tabu@siunitxfalse
+ \fi
+ \ifdefined\adl@array % <arydshln>
+ \else \let\tabu@adl@fix \relax
+ \let\tabu@adl@endtrial \@empty \fi
+ \ifdefined\longtable % <longtable>
+ \else \let\longtabu \tabu@nolongtabu \fi
+ \ifdefined\cellspacetoplimit \tabu@warn@cellspace\fi
+ \csname\ifcsname ifHy@hyperfootnotes\endcsname % <hyperfootnotes>
+ ifHy@hyperfootnotes\else iffalse\fi\endcsname
+ \let\tabu@footnotetext \tabu@Hy@ftntext
+ \let\tabu@xfootnote \tabu@Hy@xfootnote \fi
+ \ifdefined\FV@DefineCheckEnd% <fancyvrb>
+ \tabu@fancyvrb \fi
+ \ifdefined\color % <color / xcolor>
+ \let\tabu@color \color
+ \def\tabu@leavevmodecolor ##1{%
+ \def\tabu@leavevmodecolor {\leavevmode ##1}%
+ }\expandafter\tabu@leavevmodecolor\expandafter{\color}%
+ \else
+ \let\tabu@color \tabu@nocolor
+ \let\tabu@leavevmodecolor \@firstofone \fi
+ \tabu@latextwoe
+ \ifdefined\@raggedtwoe@everyselectfont % <ragged2e>
+ \tabu@raggedtwoe
+ \else
+ \let\tabu@cell@L \tabu@cell@l
+ \let\tabu@cell@R \tabu@cell@r
+ \let\tabu@cell@C \tabu@cell@c
+ \let\tabu@cell@J \tabu@cell@j \fi
+ \expandafter\in@ \expandafter\@arrayright \expandafter{\endarray}%
+ \ifin@ \let\tabu@endarray \endarray
+ \else \tabu@fix@arrayright \fi% <fix for colortbl & arydshln (delarray)>
+ \everyrow{}%
+}% \tabu@AtBeginDocument
+\def\tabu@warn@cellspace{%
+ \PackageWarning{tabu}{%
+ Package cellspace has some limitations
+ \MessageBreak And redefines some macros of array.sty.
+ \MessageBreak Please use \string\tabulinesep\space to control
+ \MessageBreak vertical spacing of lines inside tabu environnement}%
+}% \tabu@warn@cellspace
+%% tabu Package initialisation
+\tabuscantokensfalse
+\let\tabu@arc@G \relax
+\let\tabu@drsc@G \relax
+\let\tabu@evr@G \@empty
+\let\tabu@rc@G \@empty
+\def\tabu@ls@G {\tabu@linestyle@}%
+\let\tabu@@rowfontreset \@empty % <init>
+\let\tabu@@celllalign \@empty
+\let\tabu@@cellralign \@empty
+\let\tabu@@cellleft \@empty
+\let\tabu@@cellright \@empty
+\def\tabu@naturalXmin {\z@}
+\def\tabu@naturalXmax {\z@}
+\let\tabu@rowfontreset \@empty
+\def\tabulineon {4pt}\let\tabulineoff \tabulineon
+\tabu@everyrowtrue
+\ifdefined\pdfelapsedtime % <pdfTeX>
+ \def\tabu@pdftimer {\xdef\tabu@starttime{\the\pdfelapsedtime}}%
+\else \let\tabu@pdftimer \relax \let\tabu@message@etime \relax
+\fi
+\tracingtabu=\z@
+\newtabulinestyle {=\maxdimen}% creates the 'factory' settings \tabu@linestyle@
+\tabulinestyle{}
+\taburowcolors{}
+\let\tabudefaulttarget \linewidth
+\ProcessOptions* % \ProcessOptions* is quicker !
+\endinput
+%%
+%% End of file `tabu.sty'.
diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd
index e4ca883..7a65bd2 100644
--- a/templates/xml/compound.xsd
+++ b/templates/xml/compound.xsd
@@ -232,6 +232,7 @@
<xsd:complexType name="paramType">
<xsd:sequence>
+ <xsd:element name="attributes" minOccurs="0" />
<xsd:element name="type" type="linkedTextType" minOccurs="0" />
<xsd:element name="declname" minOccurs="0" />
<xsd:element name="defname" minOccurs="0" />
@@ -423,9 +424,9 @@
<xsd:element name="rtfonly" type="xsd:string" />
<xsd:element name="latexonly" type="xsd:string" />
<xsd:element name="image" type="docImageType" />
- <xsd:element name="dot" type="xsd:string" />
- <xsd:element name="msc" type="xsd:string" />
- <xsd:element name="plantuml" type="xsd:string" />
+ <xsd:element name="dot" type="docImageType" />
+ <xsd:element name="msc" type="docImageType" />
+ <xsd:element name="plantuml" type="docImageType" />
<xsd:element name="anchor" type="docAnchorType" />
<xsd:element name="formula" type="docFormulaType" />
<xsd:element name="ref" type="docRefTextType" />
@@ -456,9 +457,9 @@
<xsd:element name="table" type="docTableType" />
<xsd:element name="heading" type="docHeadingType" />
<xsd:element name="image" type="docImageType" />
- <xsd:element name="dotfile" type="docFileType" />
- <xsd:element name="mscfile" type="docFileType" />
- <xsd:element name="diafile" type="docFileType" />
+ <xsd:element name="dotfile" type="docImageType" />
+ <xsd:element name="mscfile" type="docImageType" />
+ <xsd:element name="diafile" type="docImageType" />
<xsd:element name="toclist" type="docTocListType" />
<xsd:element name="language" type="docLanguageType" />
<xsd:element name="parameterlist" type="docParamListType" />
@@ -578,16 +579,12 @@
<xsd:complexType name="docImageType" mixed="true">
<xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
- <xsd:attribute name="type" type="DoxImageKind" />
- <xsd:attribute name="name" type="xsd:string" />
- <xsd:attribute name="width" type="xsd:string" />
- <xsd:attribute name="height" type="xsd:string" />
- <xsd:attribute name="inline" type="DoxBool" />
- </xsd:complexType>
-
- <xsd:complexType name="docFileType" mixed="true">
- <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
- <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="DoxImageKind" use="optional"/>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="width" type="xsd:string" use="optional"/>
+ <xsd:attribute name="height" type="xsd:string" use="optional"/>
+ <xsd:attribute name="inline" type="DoxBool" use="optional"/>
+ <xsd:attribute name="caption" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="docTocItemType" mixed="true">
diff --git a/testing/011/interface_integer.xml b/testing/011/interface_integer.xml
index 863ec91..21d71fd 100644
--- a/testing/011/interface_integer.xml
+++ b/testing/011/interface_integer.xml
@@ -59,24 +59,24 @@
<para>An interface </para>
</detaileddescription>
<inheritancegraph>
- <node id="1">
+ <node id="2">
<label>Object</label>
</node>
- <node id="0">
+ <node id="1">
<label>Integer</label>
<link refid="interface_integer"/>
- <childnode refid="1" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
</inheritancegraph>
<collaborationgraph>
- <node id="3">
+ <node id="2">
<label>Object</label>
</node>
- <node id="2">
+ <node id="1">
<label>Integer</label>
<link refid="interface_integer"/>
- <childnode refid="3" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
</collaborationgraph>
diff --git a/testing/019/group__g1.xml b/testing/019/group__g1.xml
index d9ea16d..d6807ca 100644
--- a/testing/019/group__g1.xml
+++ b/testing/019/group__g1.xml
@@ -20,9 +20,9 @@
</memberdef>
</sectiondef>
<briefdescription>
+ <para>Text for first group. </para>
</briefdescription>
<detaileddescription>
- <para>Text for first group. </para>
</detaileddescription>
</compounddef>
</doxygen>
diff --git a/testing/019/group__g2.xml b/testing/019/group__g2.xml
index 9b1fc83..3514d89 100644
--- a/testing/019/group__g2.xml
+++ b/testing/019/group__g2.xml
@@ -21,9 +21,9 @@
</memberdef>
</sectiondef>
<briefdescription>
+ <para>Text for second group. </para>
</briefdescription>
<detaileddescription>
- <para>Text for second group. </para>
</detaileddescription>
</compounddef>
</doxygen>
diff --git a/testing/019/group__g3.xml b/testing/019/group__g3.xml
index d9137b0..0f21232 100644
--- a/testing/019/group__g3.xml
+++ b/testing/019/group__g3.xml
@@ -34,9 +34,9 @@
</memberdef>
</sectiondef>
<briefdescription>
+ <para>Text for third group. </para>
</briefdescription>
<detaileddescription>
- <para>Text for third group. </para>
</detaileddescription>
</compounddef>
</doxygen>
diff --git a/testing/021/indexpage.xml b/testing/021/indexpage.xml
index 7c93a78..3ecbd0a 100644
--- a/testing/021/indexpage.xml
+++ b/testing/021/indexpage.xml
@@ -6,7 +6,7 @@
<briefdescription>
</briefdescription>
<detaileddescription>
- <para> Our main function starts like this: <programlisting filename="example_test.cpp"><codeline><highlight class="normal">void<sp/>main()</highlight></codeline><codeline><highlight class="normal">{</highlight></codeline></programlisting> First we create a object <computeroutput>t</computeroutput> of the <ref refid="class_test" kindref="compound">Test</ref> class. <programlisting filename="example_test.cpp"><codeline><highlight class="normal"><sp/><sp/>Test<sp/>t;</highlight></codeline></programlisting> Then we call the example member function <programlisting filename="example_test.cpp"><codeline><highlight class="normal"><sp/><sp/>t.example();</highlight></codeline></programlisting> After that our little test routine ends. <programlisting filename="example_test.cpp"><codeline><highlight class="normal">}</highlight></codeline></programlisting> </para>
+ <para> Our main function starts like this: <programlisting filename="example_test.cpp"><codeline><highlight class="keywordtype">void</highlight><highlight class="normal"><sp/>main()</highlight></codeline><codeline><highlight class="normal">{</highlight></codeline></programlisting> First we create a object <computeroutput>t</computeroutput> of the <ref refid="class_test" kindref="compound">Test</ref> class. <programlisting filename="example_test.cpp"><codeline><highlight class="normal"><sp/><sp/><ref refid="class_test" kindref="compound">Test</ref><sp/>t;</highlight></codeline></programlisting> Then we call the example member function <programlisting filename="example_test.cpp"><codeline><highlight class="normal"><sp/><sp/>t.<ref refid="class_test_1a47b775f65718978f1ffcd96376f8ecfa" kindref="member">example</ref>();</highlight></codeline></programlisting> After that our little test routine ends. <programlisting filename="example_test.cpp"><codeline><highlight class="normal">}</highlight></codeline></programlisting> </para>
</detaileddescription>
</compounddef>
</doxygen>
diff --git a/testing/027/struct_car.xml b/testing/027/struct_car.xml
index 61a8d16..b3d9894 100644
--- a/testing/027/struct_car.xml
+++ b/testing/027/struct_car.xml
@@ -27,43 +27,43 @@
<para><ref refid="struct_car" kindref="compound">Car</ref> class. </para>
</detaileddescription>
<inheritancegraph>
- <node id="1">
+ <node id="2">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="2" relation="public-inheritance">
+ <childnode refid="3" relation="public-inheritance">
</childnode>
</node>
- <node id="2">
+ <node id="3">
<label>Object</label>
<link refid="struct_object"/>
</node>
- <node id="0">
+ <node id="1">
<label>Car</label>
<link refid="struct_car"/>
- <childnode refid="1" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
</inheritancegraph>
<collaborationgraph>
- <node id="4">
+ <node id="2">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="5" relation="public-inheritance">
+ <childnode refid="3" relation="public-inheritance">
</childnode>
- <childnode refid="5" relation="usage">
+ <childnode refid="3" relation="usage">
<edgelabel>base</edgelabel>
</childnode>
</node>
- <node id="5">
+ <node id="3">
<label>Object</label>
<link refid="struct_object"/>
</node>
- <node id="3">
+ <node id="1">
<label>Car</label>
<link refid="struct_car"/>
- <childnode refid="4" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
- <childnode refid="4" relation="usage">
+ <childnode refid="2" relation="usage">
<edgelabel>base</edgelabel>
</childnode>
</node>
diff --git a/testing/027/struct_object.xml b/testing/027/struct_object.xml
index 18b34ef..754906e 100644
--- a/testing/027/struct_object.xml
+++ b/testing/027/struct_object.xml
@@ -63,26 +63,26 @@
<para>Base object class. </para>
</detaileddescription>
<inheritancegraph>
- <node id="9">
+ <node id="4">
<label>Truck</label>
<link refid="struct_truck"/>
- <childnode refid="7" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
- <node id="7">
+ <node id="2">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="6" relation="public-inheritance">
+ <childnode refid="1" relation="public-inheritance">
</childnode>
</node>
- <node id="6">
+ <node id="1">
<label>Object</label>
<link refid="struct_object"/>
</node>
- <node id="8">
+ <node id="3">
<label>Car</label>
<link refid="struct_car"/>
- <childnode refid="7" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
</inheritancegraph>
diff --git a/testing/027/struct_truck.xml b/testing/027/struct_truck.xml
index 92877e3..0da26dc 100644
--- a/testing/027/struct_truck.xml
+++ b/testing/027/struct_truck.xml
@@ -27,43 +27,43 @@
<para><ref refid="struct_truck" kindref="compound">Truck</ref> class. </para>
</detaileddescription>
<inheritancegraph>
- <node id="11">
+ <node id="1">
<label>Truck</label>
<link refid="struct_truck"/>
- <childnode refid="12" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
- <node id="12">
+ <node id="2">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="13" relation="public-inheritance">
+ <childnode refid="3" relation="public-inheritance">
</childnode>
</node>
- <node id="13">
+ <node id="3">
<label>Object</label>
<link refid="struct_object"/>
</node>
</inheritancegraph>
<collaborationgraph>
- <node id="14">
+ <node id="1">
<label>Truck</label>
<link refid="struct_truck"/>
- <childnode refid="15" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
- <childnode refid="15" relation="usage">
+ <childnode refid="2" relation="usage">
<edgelabel>base</edgelabel>
</childnode>
</node>
- <node id="15">
+ <node id="2">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="16" relation="public-inheritance">
+ <childnode refid="3" relation="public-inheritance">
</childnode>
- <childnode refid="16" relation="usage">
+ <childnode refid="3" relation="usage">
<edgelabel>base</edgelabel>
</childnode>
</node>
- <node id="16">
+ <node id="3">
<label>Object</label>
<link refid="struct_object"/>
</node>
diff --git a/testing/027/struct_vehicle.xml b/testing/027/struct_vehicle.xml
index 3fc2456..40c2be2 100644
--- a/testing/027/struct_vehicle.xml
+++ b/testing/027/struct_vehicle.xml
@@ -67,40 +67,40 @@
<para><ref refid="struct_vehicle" kindref="compound">Vehicle</ref> class. </para>
</detaileddescription>
<inheritancegraph>
- <node id="20">
+ <node id="4">
<label>Truck</label>
<link refid="struct_truck"/>
- <childnode refid="17" relation="public-inheritance">
+ <childnode refid="1" relation="public-inheritance">
</childnode>
</node>
- <node id="17">
+ <node id="1">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="18" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
</node>
- <node id="18">
+ <node id="2">
<label>Object</label>
<link refid="struct_object"/>
</node>
- <node id="19">
+ <node id="3">
<label>Car</label>
<link refid="struct_car"/>
- <childnode refid="17" relation="public-inheritance">
+ <childnode refid="1" relation="public-inheritance">
</childnode>
</node>
</inheritancegraph>
<collaborationgraph>
- <node id="21">
+ <node id="1">
<label>Vehicle</label>
<link refid="struct_vehicle"/>
- <childnode refid="22" relation="public-inheritance">
+ <childnode refid="2" relation="public-inheritance">
</childnode>
- <childnode refid="22" relation="usage">
+ <childnode refid="2" relation="usage">
<edgelabel>base</edgelabel>
</childnode>
</node>
- <node id="22">
+ <node id="2">
<label>Object</label>
<link refid="struct_object"/>
</node>
diff --git a/testing/071/namespace_a_namespace_1_1_0D0.xml b/testing/071/namespace_a_namespace_1_1_0d0.xml
index 6e42714..14f5a51 100644
--- a/testing/071/namespace_a_namespace_1_1_0D0.xml
+++ b/testing/071/namespace_a_namespace_1_1_0d0.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="">
- <compounddef id="namespace_a_namespace_1_1_0D0" kind="namespace" language="C++">
+ <compounddef id="namespace_a_namespace_1_1_0d0" kind="namespace" language="C++">
<compoundname>ANamespace::@0</compoundname>
<sectiondef kind="enum">
<memberdef kind="enum" id="071__enum__in__anon__ns_8cpp_1a96ab6574751fdf6a53ceec8a3896c45d" prot="public" static="no" strong="yes">
diff --git a/testing/071_enum_in_anon_ns.cpp b/testing/071_enum_in_anon_ns.cpp
index a5b9ac8..8aab15f 100644
--- a/testing/071_enum_in_anon_ns.cpp
+++ b/testing/071_enum_in_anon_ns.cpp
@@ -1,5 +1,5 @@
// objective: test that enum values in anonymous namespaces produce no warning
-// check: namespace_a_namespace_1_1_0D0.xml
+// check: namespace_a_namespace_1_1_0d0.xml
namespace ANamespace { namespace {
diff --git a/testing/runtests.py b/testing/runtests.py
index d132da5..fa3c186 100755
--- a/testing/runtests.py
+++ b/testing/runtests.py
@@ -116,6 +116,8 @@ class Tester:
print('LATEX_OUTPUT=%s/latex' % self.test_out, file=f)
if self.args.subdirs:
print('CREATE_SUBDIRS=YES', file=f)
+ if (self.args.clang):
+ print('CLANG_ASSISTED_PARSING=YES', file=f)
if (self.args.cfgs):
for cfg in list(itertools.chain.from_iterable(self.args.cfgs)):
if cfg.find('=') == -1:
@@ -435,6 +437,9 @@ def main():
action="store_true")
parser.add_argument('--subdirs',help='use the configuration parameter CREATE_SUBDIRS=YES',
action="store_true")
+ parser.add_argument('--clang',help='use CLANG_ASSISTED_PARSING, works only when '
+ 'doxygen has been compiled with "use_libclang"',
+ action="store_true")
parser.add_argument('--keep',help='keep result directories',
action="store_true")
parser.add_argument('--cfg',nargs='+',dest='cfgs',action='append',help=
diff --git a/vhdlparser/CMakeLists.txt b/vhdlparser/CMakeLists.txt
index 71e97df..f89008c 100644
--- a/vhdlparser/CMakeLists.txt
+++ b/vhdlparser/CMakeLists.txt
@@ -1,14 +1,5 @@
-# configvalues.h
-add_custom_command(
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maph ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.h
- DEPENDS ${CMAKE_SOURCE_DIR}/src/config.xml ${CMAKE_SOURCE_DIR}/src/configgen.py
- OUTPUT ${GENERATED_SRC}/configvalues.h
-)
-set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1)
-
include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/qtools ${GENERATED_SRC})
add_library(vhdlparser STATIC
-${GENERATED_SRC}/configvalues.h
CharStream.cc
ParseException.cc
Token.cc
@@ -17,3 +8,6 @@ VhdlParser.cc
VhdlParserTokenManager.cc
VhdlParserIF.cpp
)
+add_dependencies(vhdlparser
+ generate_configvalues_header
+)
diff --git a/vhdlparser/VhdlParserTokenManager.cc b/vhdlparser/VhdlParserTokenManager.cc
index 3fe7456..a696fa6 100644
--- a/vhdlparser/VhdlParserTokenManager.cc
+++ b/vhdlparser/VhdlParserTokenManager.cc
@@ -3036,7 +3036,7 @@ int VhdlParserTokenManager::jjMoveNfa_0(int startState, int curPos){
}
} while(i != startsAt);
}
- else if (curChar < 128)
+ else if ((int)curChar < 128)
{
unsigned long long l = 1ULL << (curChar & 077);
(void)l;